我想通过一个方法提交Runnable
任务到ForkJoinPool:带有非递归任务的Java ForkJoinPool,是否可以窃取工作?
forkJoinPool.submit(Runnable task)
请注意,我用的JDK 7
引擎盖下,他们转变成ForkJoinTask对象。 我知道ForkJoinPool是有效的,当一个任务被递归分割成小的时候。
问:
是否工作窃取仍处于ForkJoinPool工作,如果没有递归?
在这种情况下值得吗?
更新1: 任务很小,可能不平衡。即使是严格相等的任务,诸如上下文切换,线程调度,停车,页面丢失等等也会导致不平衡。
更新2: Doug Lea的该Concurrency JSR-166 Interest组中写道,通过给这个一个提示:
这也大大提高了产量,当所有任务异步提交到池 而不是分叉,这将成为一种合理的 构造actor框架的方式,以及许多其他可能使用ThreadPoolExecutor的普通服务。
我认为,当谈到合理的小型CPU限制任务时,由于这种优化,ForkJoinPool是最佳选择。重点是这些任务已经很小,不需要递归分解。 工作偷窃工作,无论是大型还是小型任务 - 任务可以由另一名自由工人从繁忙工人的Deque尾巴抓取。
更新3: Scalability of ForkJoinPool - 由阿卡队乒乓的基准显示出巨大的效果。
尽管如此,要更有效地应用ForkJoinPool,还需要进行性能调整。
我已经想过这个我自己,我想这是你提到的线程的停车和锁定。这就是为什么我认为ring buffers(disruptor)比unwrapped fork join更快(至少对于我的非递归事件任务)。 –
@Adam Gent我们也使用了Disruptor - 它速度惊人。是的,RingBuffer的想法应用于许多现代数据结构中。但是,它们在使用情况上有所不同:1. Disruptor使用1个线程1用户模型进行流水线操作,但无法窃取工作,而2. FJ是一群工作人员 - 工作分布在多个线程(m:n)中。 –
我很熟悉fj-rb的差异,但我认为他们都可能会减少锁定,但我不是专家。 –