tei*_*vah 9 java executorservice forkjoinpool
我对ExecutorService和 的内部调度机制有点困惑ForkJoinPool。
我了解ExecutorService调度是通过这种方式完成的。
一堆任务在排队。一旦线程可用,它将处理第一个可用任务,依此类推。
同时, aForkJoinPool被表示为不同的,因为它使用了工作窃取算法。如果我理解正确,这意味着一个线程可以从另一个线程窃取一些任务。
然而,我并不真正理解在ExecutorService和 中实现的机制之间的区别ForkJoinPool。根据我的理解,这两种机制都应该尽可能减少每个线程的空闲时间。
我会理解,如果在 a 的情况下ExecutorService,每个线程都有自己的队列。然而,情况并非如此,因为队列由池的不同线程共享......
任何澄清将是非常受欢迎的!
Eug*_*ene 11
假设您有一个非常大的整数数组,并且您想添加所有这些整数。随着ExecutorService你可能会说:让我们除以阵列成线/ 4,所以让我们说一些块,如果你有160个元素的数组(和你有4个CPU),为您打造160 / 4 / 4 = 10,所以你将创建16块各持10整数。创建 runnables/callables 并将它们提交给 executor 服务(当然,在完成后想办法合并这些结果)。
现在您希望每个 CPU 将执行其中的 4 个任务并处理它们。现在我们还假设一些数字的添加非常复杂(当然不是,但请耐心等待),结果可能是 3 个线程/CPU 完成了它们的工作,而其中一个只忙于第一个块. 没有人想要,当然,但可能会发生。现在的坏事是你对此无能为力。
什么ForkJoinPool做的反而是说给我提供你想如何分割你的任务和最小的工作量我必须做的实施,我会采取其他的事情。在Stream API这个用做SpliteratorS; 主要有两种方法trySplit(要么返回null意味着没有任何东西可以被拆分,要么返回一个新的Spliterator- 意味着一个新的块),forEachRemaning一旦你不能再拆分你的任务,它就会处理元素。这就是窃取工作可以帮助你的地方。
你说你的块是如何计算的(通常分成两半)以及当你不能再分裂时该怎么办。ForkJoinPool将第一个块分派给所有线程,当它们中的一些空闲时 - 他们完成了他们的工作,他们可以从其他线程查询其他队列,看看他们是否有工作。如果他们注意到在其他一些线程队列中有块,他们会接受它们,自己拆分它们并处理它们。甚至可以证明他们并没有自己完成这些块的全部工作 - 一些其他线程现在可以查询该线程的队列并注意到仍有工作要做等等......这要好得多现在,当这 3 个线程空闲时,它们可以进行其他一些工作 - 而且它们都很忙。
这个例子有点简化,但与现实相去甚远。只是你需要有比 CPU/线程更多的块来窃取工作;因此通常trySplit必须有一个智能实现,并且您的流源中需要大量元素。
| 归档时间: |
|
| 查看次数: |
1640 次 |
| 最近记录: |