我对ExecutorService
和ForkJoinpool
的内部调度机制有点困惑。
同时,forkjoinpool
显示为不同的,因为它使用了工作窃取算法。如果我理解正确,它意味着一个线程可以从另一个线程窃取一些任务。
然而,我并不真正理解ExecutorService
和ForkJoinpool
中实现的机制之间的区别。从我的理解来看,两种机制都应该尽可能减少每个线程的空闲时间。
如果在ExecutorService
的情况下,每个线程都有自己的队列,我会理解的。然而,情况并非如此,因为队列是由池的不同线程共享的。
假设您有一个非常大的ints数组,并且您希望将它们全部相加。对于ExecutorService
,您可以说:让我们将该数组划分为线程数/4的块。因此,如果您有一个160个元素的数组(并且有4个CPU),则创建160/4/4=10
,因此您将创建16个块,每个块包含10个ints。创建Runnables/Callables并将其提交给executor服务(当然,一旦这些结果完成,请考虑合并这些结果的方法)。
现在,您的希望是每个CPU将承担其中的4个任务并对其进行工作。现在让我们也假设一些数字添加起来非常复杂(当然不是,但请原谅我),结果可能是3个线程/CPU完成了它们的工作,而其中一个只忙于第一个块。当然,没有人希望这样,但可能会发生。现在不好的是你对此无能为力。
相反,forkjoinpool
所做的是,为我提供如何拆分任务和实现,以减少我必须做的最小工作量,其余的由我来处理。在流API
中,这是用拆分器
完成的;主要有两个方法trysplit
(返回null
,这意味着什么都不能拆分,或者返回一个新的spliterator
,这意味着一个新的块)和foreachremaning
,一旦不能拆分任务,它将处理元素。这就是偷工作会帮助你的地方。
你说你的块是如何计算的(通常是一分为二),以及当你不能再分裂时该怎么办。ForkJoinpool
将把第一个块分派给所有线程,当其中一些线程空闲时--它们完成了工作,它们可以从其他线程查询其他队列,看看它们是否有工作。如果他们注意到其他一些线程队列中有块,他们将接收它们,单独拆分它们并处理它们。它甚至可以证明,它们自己并不完成对这些块的全部工作--其他一些线程现在可以查询该线程的队列,并注意到还有工作要做,等等...这比现在好得多,当这3个线程空闲时,他们可以拿起一些其他的工作来做--而且所有的线程都很忙。
这个例子有点简化,但离现实并不太远。只是您需要比CPU的/线程多得多的块来工作窃取;因此,通常trysplit
必须有一个聪明的实现,并且在流的源中需要很多元素。
在阅读了关于ForkJoinPool的文章之后,我尝试了一个实验,测试与普通递归相比,实际上有多快。 我以递归的方式计算了文件夹中的文件数,令我满意的是,简单的递归比执行得更好 这是我的密码。 递归任务 纯递归 null
问题内容: 我正在使用jsr166y ForkJoinPool在线程之间分配计算任务。但是我显然一定做错了。 如果创建并行度> 1(默认值为Runtime.availableProcessors();我一直在运行2-8个线程)的ForkJoinPool,我的任务就可以正常工作。但是,如果我创建并行度= 1的ForkJoinPool,则在无法预测的迭代次数后会看到死锁。 是的-设置并行度= 1是一种
从java文档, ForkJoinPool不同于其他类型的ExecutorService,主要是因为它采用了工作窃取:池中的所有线程都试图查找并执行其他活动任务创建的子任务(如果不存在,则最终阻塞等待工作)。 当大多数任务产生其他子任务时(就像大多数ForkJoinTasks一样),这可以实现高效处理。当在构造函数中将asyncMode设置为true时,ForkJoinPools也可能适合用于从未
我有一个ExecutorService创建如下- 我有一个元素列表(list)和一个操作(称为a),我需要对列表中的每个元素应用该操作。列表可以包含1到1000之间的任意数量的元素。该操作的类型为Callable。在操作A内部,它调用其他2个服务B和C。B和C也作为异步操作运行,并提交到同一线程池。 我为每个人创建了一个异步任务来并行执行,如下所示: 现在我有了一个未来的列表,我在上面循环得到结果
我正在做一个项目,我们计划使用WLP (WebSphere liberty)代替传统的WAS。 代码使用 WAS 调度程序来调度活动。 liberty 是否也具有与 WAS 中存在的相同级别的调度程序支持/功能? 如何将调度程序任务从webphere迁移到自由?
代码: 我有上面的代码来并行执行一些任务。考虑到已经让调用线程等待完成,不知道它是否应该是而不是块中的。 注意:仅从输入列表中读取。