2016-02-26 60 views
2

我有一个ExecutorService的创建如下 -的ExecutorService和ForkJoinPool

ExecutorService executorSer = Executors.newFixedThreadPool(SIZE); 

我有元件(LIST)和操作(称为A),我需要应用在此列表中的每个元件上的列表。该列表可以包含1到1000之间的任意数量的元素。 该操作的类型为Callable。 在Operation-A内部,它调用了2个其他服务B和C. B和C也作为异步操作运行并提交给相同的线程池。

CompletionService<T> completionService = new ExecutorCompletionService<T>(executorSer); 
completionService.submit(A) // this returns a Future<T> 

现在我有未来的名单,我遍历得到()结果:

我有如下会为每个异步任务并行执行这一点。

如果我有一个非常大的线程池和LIST中的少量元素,一切正常。 但是,如果线程池SIZE很小并且LIST大小很大,我会遇到死锁。 这是因为所有Operation-A请求都很快提交并占用线程池中的所有线程。并且每个操作-A在其提交的操作B和C的Future.get()上被阻止。操作B和C任务只是坐在队列中等待获得一个线程。

因此,为了解决这个问题,我改用了ForkJoinPool。我简单地更换的newFixedThreadPool与ForkJoinPool如下

ExecutorService executorSer = new ForkJoinPool(SIZE); 

,离开了其余代码相同。

这解决了我的问题。如果线程池SIZE很小并且LIST大小很大,现在没有死锁。 我的问题是,为什么? 此外,当我打印线程名称,我看到线程数大于SIZE。它只是产生新的线程来解决僵局?

+0

更正:final ExecutorService executorSer = new ForkJoinPool(SIZE);是我用过的。 @iullianr:谢谢你指出。 – Patt

回答

0

java.util.concurrent.Executors类中没有Executors.ForkJoinPool(SIZE)方法。但是,创建ForkJoinPool的方法有Executors.newWorkStealingPool(int parallelism)。作为Java API被提:

的并行级别对应于线程 的最大数量的积极参与,或可搞的,任务处理。 线程的实际数量可能会动态增长和减少。

有你的答案。您提供的参数不是执行程序将管理的实际线程的最大数量(例如FixedThreadPool执行程序就是这种情况)。

+0

我已经使用了以下,它的工作原理。 SIZE意味着什么?这是否意味着在给定的时间系统中可以有最多的SIZE线程数?最终ExecutorService executorSer =新的ForkJoinPool(SIZE); – Patt

+0

它表示执行程序要使用的工作线程数。为了不创建大量的线程,如果它们没有足够的机器上的处理器,建议将您的值设置为Runtime.availableProcessors()以便不会并行运行 – iullianr