中的Java。完全参考》,我们读到:"一般来说,ForkJoinTask不应该使用同步方法或同步代码块。
一般来说,ForkJoinTask不应该使用同步的方法或同步的代码块。此外,你通常不会希望让compute( )方法使用其他类型的同步,例如信号体。
为什么在compute()中要避免同步,在某些情况下还可以使用semaphore或synchronized等同步方式吗,我还应该使用什么方法,从 java.util.concurrent
是否可以像ForkJoinTask和同步一样拥有可伸缩的线程数?
如果你确信它们不会长时间阻塞,你可以使用使用同步方法或同步代码块。至少,它们不应该调用到 Object.wait()
和 Semaphore.aquire()
因为这些方法会无限期地阻塞当前线程,而这种阻塞的结果要么是内存溢出,当线程池试图创建新的线程来替换被阻塞的线程时,要么是线程饥饿(一种死锁),即没有可用的线程,所有的工作永远停止。
这对各种线程池都是如此,不仅是对 ForkjoinPool
,而且对于各种异步任务,不仅是 ForkJoinTask
.
来自 Javadoc (重点是我的)。
ForkJoinTask是Future的一种轻量级形式。ForkJoinTasks的效率来自于一组限制(只在部分状态下可执行),反映了 它们的主要用途是作为计算任务,计算纯函数或对纯孤立的对象进行操作。. 主要的协调机制是安排异步执行的fork()和在任务的结果没有计算出来之前不进行的join()。计算最好避开同步的方法或区块,除了加入其他任务或之外,应尽量减少其他阻塞的同步 使用同步器(如Phasers),这些同步器被宣传为与forkjoin调度合作。.