java.util.concurrent : calculating primes
I'm new to the package java.util.concurrent. I've created the following program testing if a number is a prime using a multi and a monothreaded strategy.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class IsPrime
implements Runnable
{
private static final long UPPER_BOUND=100000;
long value;//the number observed
private IsPrime(long value)
{
this.value=value;
}
/** returns wether value is a prime number (simple and stupid method ) */
private boolean isAPrimeNumber()
{
if(value==1 || value==2) return true;
if(value%2L==0) return false;
for(long i=3;i< value;++i)
{
if(this.value%i==0) return false;
}
return true;
}
@Override
/** calls isAPrimeNumber */
public void run()
{
boolean result=isAPrimeNumber();
//if(result) System.out.println("["+this.value+"]");
}
/** loop from 3 to UPPER_BOUND, multithreaded */
private static long loopMT()
{
long now=System.currentTimeMillis();
ExecutorService service=Executors.newFixedThreadPool(10);
for(long i=3;i< UPPER_BOUND;i+=2)
{
service.submit(new IsPrime(i));
}
service.shutdown();
return System.currentTimeMillis()-now;
}
/** loop from 3 to UPPER_BOUND, NOT multithreaded */
private static long loop()
{
long now=System.currentTimeMillis();
for(long i=3;i< UPPER_BOUND;i+=2)
{
new IsPrime(i).run();
}
return System.currentTimeMillis()-now;
}
public static void main(String[] args)
{
long n1=IsPrime.loop();
long n2=IsPrime.loopMT();
System.o开发者_C百科ut.println(""+n1+" >>> "+n2);
}
}
for the method loopMT, is it the correct way to use the classes of the package java.util.concurrent ? Is there another, (safer, more elegant) way to write this program ? Can I use System.out in a multithreaded environement ?
Many thanks for your suggestions
Pierre
As System.out
is an instance of PrintStream
it is thread-safe. So it is fine for training examples. But generally output from different threads doesn't seem like a good idea to me. It's better to have dedicated output thread that accepts requests for output asynchronously.
Probably, I'd rather implemented Callable<Boolean>
as finnw suggested, otherwise I see no reason in IsPrime
class except of CPU consumption.
As it is currently written loopMT
is not waiting for the submitted tasks to complete.
You have a few options:
- Call
awaitTermination()
to wait for all primality tests to complete, writing the results toSystem.out
as you are currently doing. - Change the interface from
Runnable
toCallable<Boolean>
or maybeCallable<Map.Entry<Long, Boolean>>
and useservice.invokeAll()
(then you will get all results returned at once.) - Store the results in a synchronized
Map
and read it when all the primality tests have completed - Have the
run
method send the results to aBlockingQueue
orSynchronousQueue
and have theloopMT
method loop fetching the results from the queue and printing them. This is the option I would prefer. - Use a queue indirectly, via a
CompletionService
.
Since this calculation is likely CPU bound, there is no advantage to running more threads than you have CPU cores. Extra threads after that only add to overhead.
精彩评论