首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >向ThreadPool中的可变线程数提交可调用任务

向ThreadPool中的可变线程数提交可调用任务
EN

Code Review用户
提问于 2015-03-26 16:57:02
回答 1查看 675关注 0票数 2

我正在进入多线程处理,我想知道下面的代码是否是好的实践。这是我第一次尝试多线程。

是否有更好的方法从Future<Integer>中获取值,而不是将它们保存在列表中,然后进行汇总?

代码语言:javascript
复制
 // Counting the number of prime-numbers from 'from' to 'to' by using 'nrThreas' amount of threads.
public static int countParallel(final int from, final int to, final int nrThreads) throws ExecutionException, InterruptedException {

    int count = 0;
    int startFrom = 0;
    int numbersPerThread = (to - from)/nrThreads;

    ExecutorService threadPool = Executors.newFixedThreadPool(nrThreads);

    Future<Integer> countHelper = null;

    // Storing the futures in order to get the Integers after the tasks were submitted to its threads
    ArrayList<Future<Integer>> helperList = new ArrayList<>();

    // determining the amount if prime-numbers between 1 and 20.000.000.
    for(int i = 0; i < nrThreads; i++)
    {
        countHelper = threadPool.submit(new PrimeCounter(startFrom, startFrom + numbersPerThread));

        // gets the next chunk to be examined
        startFrom += numbersPerThread + 1;

        helperList.add(countHelper);

    }

    threadPool.shutdown();

    // summing up the helper.get() from the list
    for(Future<Integer> helper : helperList)
    {
        count += helper.get();
    }

    return count;
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2015-03-26 20:10:02

一般关注

与多线程无关:您可能需要考虑篱笆柱错误-考虑:

代码语言:javascript
复制
Assert.assertEquals(countParallel(8,10,2), countParallel(8,10,1));

很明显,您提供的代码将通过此测试吗?

此外,如果变量仅在给定范围内使用,则最好在范围内声明该变量.

代码语言:javascript
复制
for(int i = 0; i < nrThreads; i++)
{
    Future<Integer> countHelper = threadPool.submit(new PrimeCounter(startFrom, startFrom + numbersPerThread));

    // gets the next chunk to be examined
    startFrom += numbersPerThread + 1;

    helperList.add(countHelper);

}

..。并在范围内,尽可能接近第一次使用该变量:

代码语言:javascript
复制
int count = 0;
for(Future<Integer> helper : helperList)
{
    count += helper.get();
}

我发现这样做也揭示了重构--例如,将所有作业的输出折叠成一个数字是一个单一的想法。

代码语言:javascript
复制
int sum(List<Future<Integer>> resultList) {
    int count = 0;
    for(Future<Integer> helper : helperList)
    {
        count += helper.get();
    }
    return count;
}

Multi-Threading

好处是:您创建了一个ExecutorService,而不是创建自己的线程。十分之十。

你已经完全取消了。如果抛出InterruptedException,应该对正在运行的作业做些什么?对于玩具问题,如果你不支持取消正在进行的工作的能力,那就好了。把它写在待会儿要拿的东西清单上。

也许,你在分担工作时也有点胆小。一个替代给每个线程它自己的工作,是提供大量的工作,并让执行者服务决定哪个线程可以做什么。将7个作业提交给有6个线程的ExecutorService没有什么问题;就这一点而言,它可能是70个作业。或者700个工作岗位。

您希望避免的情况是,大多数线程都处于空闲状态(因为没有更多可用的工作),但是一个线程花费了很长时间,因为他掌握了问题的所有困难部分。

因此,最好更公平地分配工作--告诉每个PrimeCounter您正在求解范围1,20.000.000,但是质数计数器处理列表中的每个nTh条目(例如:一个PrimeCounter检查0,6,12.,下一个PrimeCounter检查1,7,13.,最后一个检查5,11,17…)。

是否有更好的方法从未来获得价值,而不是把它们保存在一个清单中,然后总结它们呢?

我认为这里的答案是:视情况而定。这里所做的好事情之一是确保值只由一个线程编写;这使得许多事情更容易推理(例如,与尝试让每个PrimeCounter将值添加到公共累加器相比)。

在这里,如果您使用的结果非常接近于开始作业的位置,则可能更容易将中间结果存储在Runnable中,等待所有线程完成,然后迭代Runnables来总结总数。您可以使用ExecutorService.awaitTermination来知道作业何时完成运行,或将其设置为通过CountDownLatch向每个任务发送结果信号,或.

如果结果的消耗“更远离”计算,我将更倾向于使用Future;就像在抽象层的另一端一样。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/85084

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档