我正在进入多线程处理,我想知道下面的代码是否是好的实践。这是我第一次尝试多线程。
是否有更好的方法从Future<Integer>中获取值,而不是将它们保存在列表中,然后进行汇总?
// 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;
}发布于 2015-03-26 20:10:02
与多线程无关:您可能需要考虑篱笆柱错误-考虑:
Assert.assertEquals(countParallel(8,10,2), countParallel(8,10,1));很明显,您提供的代码将通过此测试吗?
此外,如果变量仅在给定范围内使用,则最好在范围内声明该变量.
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);
}..。并在范围内,尽可能接近第一次使用该变量:
int count = 0;
for(Future<Integer> helper : helperList)
{
count += helper.get();
}我发现这样做也揭示了重构--例如,将所有作业的输出折叠成一个数字是一个单一的想法。
int sum(List<Future<Integer>> resultList) {
int count = 0;
for(Future<Integer> helper : helperList)
{
count += helper.get();
}
return count;
}好处是:您创建了一个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;就像在抽象层的另一端一样。
https://codereview.stackexchange.com/questions/85084
复制相似问题