2

我是包java.util.concurrent的新手。我使用多线程和单线程策略创建了以下程序测试数字是否为素数。

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.out.println(""+n1+" >>> "+n2);   
        }
    }

对于方法loopMT ,它是使用包java.util.concurrent的类的正确方法吗?还有另一种(更安全,更优雅)的方式来编写这个程序吗?我可以在多线程环境中使用 System.out 吗?

非常感谢您的建议

皮埃尔

4

3 回答 3

2

System.out它的一个实例PrintStream是线程安全的。因此,它可以用于训练示例。但通常来自不同线程的输出对我来说似乎不是一个好主意。最好有专门的输出线程来异步接受输出请求。

可能,我宁愿Callable<Boolean>按照 finnw 的建议来实现,否则IsPrime除了 CPU 消耗之外,我在课堂上看不到任何理由。

于 2010-01-28T09:57:17.733 回答
1

正如目前所写loopMT的那样,不等待提交的任务完成。

你有几个选择:

  • 调用awaitTermination()以等待所有素性测试完成,将结果写入System.out您当前正在执行的操作。
  • 将界面从 更改RunnableCallable<Boolean>或可能Callable<Map.Entry<Long, Boolean>>并使用service.invokeAll()(然后您将立即返回所有结果。)
  • 将结果存储在同步中Map,并在所有素性测试完成后读取
  • run方法将结果发送到BlockingQueueorSynchronousQueue并让loopMT方法循环从队列中获取结果并打印它们。这是我更喜欢的选项。
  • 通过CompletionService.
于 2010-01-28T09:54:21.763 回答
1

由于此计算可能受 CPU 限制,因此运行比 CPU 内核更多的线程没有任何优势。之后的额外线程只会增加开销。

于 2010-01-28T09:54:53.803 回答