ForkJoinPool似乎浪费了一个线程 [英] ForkJoinPool seems to waste a thread

查看:743
本文介绍了ForkJoinPool似乎浪费了一个线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在比较测试程序的两个变体。两者都使用4线程 ForkJoinPool 在具有四个核心的计算机上。

I'm comparing two variations on a test program. Both are operating with a 4-thread ForkJoinPool on a machine with four cores.

在'模式1'中,我非常喜欢使用池执行人服务。我将一堆任务扔进 ExecutorService.invokeAll 。我获得了比普通的固定线程执行程序服务更好的性能(即使有调用Lucene,在那里执行一些I / O)。

In 'mode 1', I use the pool very much like an executor service. I toss a pile of tasks into ExecutorService.invokeAll. I get better performance than from an ordinary fixed thread executor service (even though there are calls to Lucene, that do some I/O, in there).

没有在这里分而治之。从字面上看,我做了

There is no divide-and-conquer here. Literally, I do

ExecutorService es = new ForkJoinPool(4);
es.invokeAll(collection_of_Callables);

在'模式2'中,我向池中提交一个任务,并在该任务中调用ForkJoinTask .invoke所有提交子任务。所以,我有一个继承自 RecursiveAction 的对象,并将其提交给池。在该类的compute方法中,我对来自不同类的对象集合调用 invokeAll ,该类也继承自 RecursiveAction 。出于测试目的,我只提交第一个对象的一次一个。我天真地期望看到所有四个线程忙什么,因为调用 invokeAll 的线程将为自己获取一个子任务而不仅仅是坐着和阻塞。我可以想一些为什么它可能不会那样工作的原因。

In 'mode 2', I submit a single task to the pool, and in that task call ForkJoinTask.invokeAll to submit the subtasks. So, I have an object that inherits from RecursiveAction, and it is submitted to the pool. In the compute method of that class, I call the invokeAll on a collection of objects from a different class that also inherits from RecursiveAction. For testing purposes, I submit only one-at-a-time of the first objects. What I naively expected to see what all four threads busy, as the thread calling invokeAll would grab one of the subtasks for itself instead of just sitting and blocking. I can think of some reasons why it might not work that way.

在VisualVM中观察,在模式2中,一个线程几乎总是在等待。我希望看到的是调用invokeAll的线程立即开始处理其中一个被调用的任务,而不仅仅是静坐。这肯定比使用普通线程池尝试此方案所导致的死锁更好,但仍然是什么?它是否保留一个线程,以防其他东西被提交?如果是这样,为什么不在模式1中出现同样的问题?

Watching in VisualVM, in mode 2, one thread is pretty nearly always waiting. What I expect to see is the thread calling invokeAll immediately going to work on one of the invoked tasks rather than just sitting still. This is certainly better than the deadlocks that would result from trying this scheme with an ordinary thread pool, but still, what up? Is it holding one thread back in case something else gets submitted? And, if so, why not the same problem in mode 1?

到目前为止,我一直在使用添加到java 1.6的引导类路径的jsr166 jar来运行它。

So far I've been running this using the jsr166 jar added to java 1.6's boot class path.

推荐答案

ForkJoinTask.invokeAll正在分配所有任务,但是列表中的第一个。它自己运行的第一个任务。然后它加入其他任务。它的线程不会以任何方式释放到池中。所以你看到的是,它完成其他任务的线程阻塞。

ForkJoinTask.invokeAll is forking all tasks, but the first in the list. The first task it runs itself. Then it joins other tasks. It's thread is not released in any way to the pool. So you what you see, it it's thread blocking on other tasks to be complete.

这篇关于ForkJoinPool似乎浪费了一个线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆