Module java.base

Class ForkJoinPool

所有已实现的接口:
AutoCloseable, Executor, ExecutorService

public class ForkJoinPool extends AbstractExecutorService
用于运行 ForkJoinTaskExecutorServiceForkJoinPool 提供了非 ForkJoinTask 客户端提交的入口点,以及管理和监控操作。

ForkJoinPool 与其他类型的 ExecutorService 主要的区别在于采用了 work-stealing:池中的所有线程都尝试查找并执行提交给池的任务和/或由其他活动任务创建的任务(如果没有任务存在,则最终会阻塞等待工作)。 当大多数任务生成其他子任务(大多数 ForkJoinTask 都是如此)时,以及当许多小任务从外部客户端提交到池中时,这使得处理效率很高。特别是在构造函数中将 asyncMode 设置为 true 时,ForkJoinPool 也可能适用于永远不会被合并的事件式任务。 所有工作线程都使用 Thread.isDaemon() 设置为 true 进行初始化。

一个静态的 commonPool() 可用于大多数应用程序。 通常情况下,通用池由任何未明确提交到指定池的 ForkJoinTask 使用。 使用通用池通常会减少资源使用(在非使用期间,其线程会逐渐回收,并在后续使用时重新启动)。

对于需要单独或自定义池的应用程序,可以使用给定的目标并行级别构造一个 ForkJoinPool;默认情况下等于可用处理器的数量。 该池尝试通过动态添加、挂起或恢复内部工作线程来保持足够的活动(或可用)线程,即使一些任务因等待加入其他任务而停滞。 但是,在面对阻塞 I/O 或其他未受管理的同步时,不能保证不会进行此类调整。 嵌套的 ForkJoinPool.ManagedBlocker 接口使得可以扩展所容纳的同步类型。 可以使用具有与文档中类 ThreadPoolExecutor 中记录的参数对应的构造函数覆盖默认策略。

除了执行和生命周期控制方法之外,此类还提供了状态检查方法(例如 getStealCount())旨在帮助开发、调整和监视 fork/join 应用程序。 此外,方法 toString() 返回池状态的指示,以便进行非正式监视。

与其他 ExecutorServices 一样,以下表格总结了三种主要的任务执行方法。 这些方法主要设计供当前池中尚未参与 fork/join 计算的客户端使用。 这些方法的主要形式接受 ForkJoinTask 的实例,但重载形式还允许混合执行普通的基于 RunnableCallable 的活动。 但是,已在池中执行的任务通常应该使用表中列出的用于计算内部的形式,除非使用通常不会被合并的异步事件式任务,在这种情况下,选择方法几乎没有区别。

任务执行方法摘要
从非 fork/join 客户端调用 从 fork/join 计算中调用
安排异步执行 execute(ForkJoinTask) ForkJoinTask.fork()
等待并获取结果 invoke(ForkJoinTask) ForkJoinTask.invoke()
安排执行并获取 Future submit(ForkJoinTask) ForkJoinTask.fork()(ForkJoinTasks 是 Futures)

用于构造通用池的参数可以通过设置以下 系统属性 进行控制:

如果没有通过系统属性提供线程工厂,则通用池将使用一个使用系统类加载器作为 线程上下文类加载器 的工厂。 此外,如果存在 SecurityManager,则通用池将使用一个提供未启用 Permissions 并且不能保证跨任务保留 ThreadLocal 变量值的线程的工厂。 在建立这些设置时发生任何错误时,将使用默认参数。 可以通过将并行性属性设置为零和/或使用可能返回 null 的工厂来禁用或限制通用池中的线程使用。 但是这样做可能会导致未加入的任务永远不会被执行。
实现注意事项:
此实现将运行线程的最大数量限制为 32767。 尝试创建超过最大数量的池将导致 IllegalArgumentException。 此外,此实现仅在池关闭或内部资源耗尽时拒绝提交的任务(即通过抛出 RejectedExecutionException)。
自 JDK 版本:
1.7
  • Field Details

    • defaultForkJoinWorkerThreadFactory

      public static final ForkJoinPool.ForkJoinWorkerThreadFactory defaultForkJoinWorkerThreadFactory
      创建一个新的ForkJoinWorkerThread。除非在ForkJoinPool构造函数中被覆盖,否则将使用此工厂。
  • Constructor Details

    • ForkJoinPool

      public ForkJoinPool()
      创建一个具有与Runtime.availableProcessors()相等的并行性的ForkJoinPool,对于所有其他参数使用默认值(参见ForkJoinPool(int, ForkJoinWorkerThreadFactory, UncaughtExceptionHandler, boolean, int, int, int, Predicate, long, TimeUnit))。
      抛出:
      SecurityException - 如果存在安全管理器并且调用者无权修改线程,因为它没有持有RuntimePermission("modifyThread")
    • ForkJoinPool

      public ForkJoinPool(int parallelism)
      创建具有指定并行级别的ForkJoinPool,对于所有其他参数使用默认值(参见ForkJoinPool(int, ForkJoinWorkerThreadFactory, UncaughtExceptionHandler, boolean, int, int, int, Predicate, long, TimeUnit))。
      参数:
      parallelism - 并行级别
      抛出:
      IllegalArgumentException - 如果并行级别小于等于零,或大于实现限制
      SecurityException - 如果存在安全管理器并且调用者无权修改线程,因为它没有持有RuntimePermission("modifyThread")
    • ForkJoinPool

      public ForkJoinPool(int parallelism, ForkJoinPool.ForkJoinWorkerThreadFactory factory, Thread.UncaughtExceptionHandler handler, boolean asyncMode)
      创建具有给定参数的ForkJoinPool(对于其他参数使用默认值 -- 参见ForkJoinPool(int, ForkJoinWorkerThreadFactory, UncaughtExceptionHandler, boolean, int, int, int, Predicate, long, TimeUnit))。
      参数:
      parallelism - 并行级别。默认值,请使用Runtime.availableProcessors()
      factory - 用于创建新线程的工厂。默认值,请使用defaultForkJoinWorkerThreadFactory
      handler - 用于处理由于执行任务时遇到无法恢复的错误而终止的内部工作线程的处理程序。默认值,请使用null
      asyncMode - 如果为true,则建立本地先进先出调度模式,用于从未加入的分叉任务。在仅处理事件样式异步任务的应用程序中,此模式可能比默认的本地基于堆栈的模式更合适。默认值,请使用false
      抛出:
      IllegalArgumentException - 如果并行级别小于等于零,或大于实现限制
      NullPointerException - 如果工厂为null
      SecurityException - 如果存在安全管理器并且调用者无权修改线程,因为它没有持有RuntimePermission("modifyThread")
    • ForkJoinPool

      public ForkJoinPool(int parallelism, ForkJoinPool.ForkJoinWorkerThreadFactory factory, Thread.UncaughtExceptionHandler handler, boolean asyncMode, int corePoolSize, int maximumPoolSize, int minimumRunnable, Predicate<? super ForkJoinPool> saturate, long keepAliveTime, TimeUnit unit)
      使用给定参数创建ForkJoinPool
      参数:
      parallelism - 并行级别。对于默认值,请使用Runtime.availableProcessors()
      factory - 用于创建新线程的工厂。对于默认值,请使用defaultForkJoinWorkerThreadFactory
      handler - 用于处理由于执行任务时遇到不可恢复错误而终止的内部工作线程。对于默认值,请使用null
      asyncMode - 如果为true,则为从未加入的分叉任务建立本地先进先出调度模式。在应用程序中,工作线程仅处理事件样式的异步任务时,此模式可能比默认的本地基于堆栈的模式更合适。对于默认值,请使用false
      corePoolSize - 保持在池中的线程数(除非在经过经过一段时间的保持活动后超时)。通常(默认情况下)这与并行级别相同,但如果任务经常阻塞,则可以将其设置为较大的值以减少动态开销。使用较小的值(例如0)具有与默认值相同的效果。
      maximumPoolSize - 允许的最大线程数。当达到最大值时,替换被阻塞的线程的尝试将失败。(但是,由于不同线程的创建和终止可能重叠,并且可能由给定的线程工厂管理,因此该值可能会短暂超过。)为了安排与默认用于公共池的相同值,使用256加上parallelism级别。(默认情况下,公共池允许最多256个空闲线程。)使用一个值(例如 Integer.MAX_VALUE)大于实现的总线程限制具有与使用此限制相同的效果(这是默认值)。
      minimumRunnable - 未被加入或ForkJoinPool.ManagedBlocker阻塞的核心线程的最小允许数量。为了确保进度,当存在太少的未阻塞线程并且可能存在未执行的任务时,将构造新线程,直到达到给定的maximumPoolSize。对于默认值,请使用 1,以确保活力。较大的值可能会在存在阻塞活动时提高吞吐量,但可能不会,因为增加了开销。当提交的任务不能具有需要额外线程的依赖关系时,值为零可能是可以接受的。
      saturate - 如果非空,则在尝试创建超过最大允许总线程数时调用的谓词。默认情况下,当线程即将在加入或ForkJoinPool.ManagedBlocker上阻塞,但无法替换因为将超过maximumPoolSize时,将抛出RejectedExecutionException。但是,如果此谓词返回true,则不会抛出异常,因此池将继续以少于目标可运行线程数运行,这可能不会确保进度。
      keepAliveTime - 上次使用后经过的时间,线程将被终止(然后在需要时替换)。对于默认值,请使用60, TimeUnit.SECONDS
      unit - keepAliveTime参数的时间单位
      抛出:
      IllegalArgumentException - 如果并行级别小于或等于零,或大于实现限制,或如果maximumPoolSize小于parallelism,或如果keepAliveTime小于或等于零。
      NullPointerException - 如果工厂为null
      SecurityException - 如果存在安全管理器并且调用方不被允许修改线程,因为它不持有RuntimePermission("modifyThread")
      自从:
      9
  • Method Details

    • commonPool

      public static ForkJoinPool commonPool()
      返回公共池实例。此池是静态构建的;其运行状态不受尝试shutdown()shutdownNow()的影响。但是,此池和任何正在进行的处理将在程序System.exit(int)时自动终止。任何依赖于异步任务处理在程序终止之前完成的程序应在退出之前调用commonPool().awaitQuiescence
      返回:
      公共池实例
      自从:
      1.8
    • invoke

      public <T> T invoke(ForkJoinTask<T> task)
      执行给定任务,在完成时返回其结果。如果计算遇到未经检查的异常或错误,则将其重新抛出作为此调用的结果。重新抛出的异常的行为与常规异常相同,但在可能的情况下,包含堆栈跟踪(例如使用ex.printStackTrace()显示的堆栈跟踪)当前线程以及实际遇到异常的线程;最少只有后者。
      类型参数:
      T - 任务结果的类型
      参数:
      task - 任务
      返回:
      任务的结果
      抛出:
      NullPointerException - 如果任务为null
      RejectedExecutionException - 如果无法安排任务执行
    • execute

      public void execute(ForkJoinTask<?> task)
      安排给定任务的(异步)执行。
      参数:
      task - 任务
      抛出:
      NullPointerException - 如果任务为null
      RejectedExecutionException - 如果无法安排任务执行
    • execute

      public void execute(Runnable task)
      从接口复制的描述: Executor
      在将来的某个时间执行给定命令。命令可以在新线程中执行,在池线程中执行,或在调用线程中执行,由Executor实现自行决定。
      参数:
      task - 可运行任务
      抛出:
      NullPointerException - 如果任务为null
      RejectedExecutionException - 如果无法安排任务执行
    • submit

      public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task)
      提交一个ForkJoinTask以执行。
      实现要求:
      当从不在此池中的线程调用时,此方法等效于externalSubmit(ForkJoinTask)
      类型参数:
      T - 任务结果的类型
      参数:
      task - 要提交的任务
      返回:
      任务
      抛出:
      NullPointerException - 如果任务为null
      RejectedExecutionException - 如果无法安排任务执行
    • submit

      public <T> ForkJoinTask<T> submit(Callable<T> task)
      从接口复制的描述: ExecutorService
      提交一个返回值任务以执行,并返回代表任务待处理结果的Future。Future的get方法将在成功完成时返回任务的结果。

      如果您希望立即阻塞等待任务,可以使用以下形式的构造:result = exec.submit(aCallable).get();

      注意:Executors类包括一组方法,可以将其他常见的类似闭包对象(例如,PrivilegedAction)转换为Callable形式,以便提交。

      指定者:
      submit 在接口 ExecutorService
      覆盖:
      submit 在类 AbstractExecutorService
      类型参数:
      T - 任务结果的类型
      参数:
      task - 要提交的任务
      返回:
      代表任务待完成的Future
      抛出:
      NullPointerException - 如果任务为null
      RejectedExecutionException - 如果无法安排任务执行
    • submit

      public <T> ForkJoinTask<T> submit(Runnable task, T result)
      从接口复制的描述: ExecutorService
      提交一个Runnable任务以执行,并返回代表该任务的Future。Future的get方法将在成功完成时返回给定的结果。
      指定者:
      submit 在接口 ExecutorService
      覆盖:
      submit 在类 AbstractExecutorService
      类型参数:
      T - 结果的类型
      参数:
      task - 要提交的任务
      result - 要返回的结果
      返回:
      代表任务待完成的Future
      抛出:
      NullPointerException - 如果任务为null
      RejectedExecutionException - 如果无法安排任务执行
    • submit

      public ForkJoinTask<?> submit(Runnable task)
      从接口复制的描述: ExecutorService
      提交一个Runnable任务以执行,并返回代表该任务的Future。Future的get方法在成功完成时将返回null
      指定者:
      submit 在接口 ExecutorService
      覆盖:
      submit 在类 AbstractExecutorService
      参数:
      task - 要提交的任务
      返回:
      代表任务待完成的Future
      抛出:
      NullPointerException - 如果任务为null
      RejectedExecutionException - 如果无法安排任务执行
    • externalSubmit

      public <T> ForkJoinTask<T> externalSubmit(ForkJoinTask<T> task)
      将给定任务提交,就好像从非ForkJoinTask客户端提交一样。即使从池中的线程调用,该任务也会被添加到调度队列以提交到池中。
      实现要求:
      当从不在此池中的线程调用时,此方法等效于submit(ForkJoinTask)
      类型参数:
      T - 任务结果的类型
      参数:
      task - 要提交的任务
      返回:
      任务
      抛出:
      NullPointerException - 如果任务为null
      RejectedExecutionException - 如果无法安排任务执行
      自:
      20
    • lazySubmit

      public <T> ForkJoinTask<T> lazySubmit(ForkJoinTask<T> task)
      提交给定任务,但不保证在没有可用活动线程的情况下最终执行。在某些情况下,此方法可能通过依赖于特定上下文的知识,减少争用和开销,因为现有线程(可能包括在此池中操作的调用线程)最终将可用于执行任务。
      类型参数:
      T - 任务结果的类型
      参数:
      task - 任务
      返回:
      任务
      抛出:
      NullPointerException - 如果任务为null
      RejectedExecutionException - 如果无法安排任务执行
      自:
      19
    • setParallelism

      public int setParallelism(int size)
      更改此池的目标并行性,控制工作线程的未来创建、使用和终止。应用程序包括处理随时间变化的可用处理器数量的情况。
      实现说明:
      此实现将运行线程的最大数量限制为32767
      参数:
      size - 目标并行性级别
      返回:
      先前的并行性级别。
      抛出:
      IllegalArgumentException - 如果大小小于1或大于此池支持的最大值
      UnsupportedOperationException - 这是commonPool(),并行性级别由系统属性java.util.concurrent.ForkJoinPool.common.parallelism设置。
      SecurityException - 如果存在安全管理器并且调用方不被允许修改线程,因为它没有持有RuntimePermission("modifyThread")
      自:
      19
    • invokeAll

      public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
      从接口复制的描述: ExecutorService
      执行给定任务,返回一个包含它们状态和结果的Future列表,当所有任务完成时。对于返回列表的每个元素,Future.isDone()都为true。请注意,已完成的任务可能是正常终止,也可能是通过抛出异常终止。如果在此操作进行时修改给定集合,则此方法的结果是未定义的。
      类型参数:
      T - 从任务返回的值的类型
      参数:
      tasks - 任务集合
      返回:
      代表任务的Future列表,与给定任务列表的迭代器产生的顺序相同,每个任务都已完成
      抛出:
      NullPointerException - 如果任务或其任何元素为null
      RejectedExecutionException - 如果任何任务无法安排执行
    • getFactory

      返回用于构造新工作线程的工厂。
      返回:
      用于构造新工作线程的工厂
    • getUncaughtExceptionHandler

      public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()
      返回在执行任务时由于遇到无法恢复的错误而终止的内部工作线程的处理程序。
      返回:
      处理程序,如果没有则为null
    • getParallelism

      public int getParallelism()
      返回此池的目标并行性级别。
      返回:
      此池的目标并行性级别
    • getCommonPoolParallelism

      public static int getCommonPoolParallelism()
      返回公共池的目标并行性级别。
      返回:
      公共池的目标并行性级别
      自:
      1.8
    • getPoolSize

      public int getPoolSize()
      返回已启动但尚未终止的工作线程数。此方法返回的结果可能与getParallelism()不同,当创建线程以保持并行性时,其他线程被协作地阻塞。
      返回:
      工作线程数
    • getAsyncMode

      public boolean getAsyncMode()
      如果此池使用本地先进先出调度模式处理从未加入的分叉任务,则返回true
      返回:
      如果此池使用异步模式,则返回true
    • getRunningThreadCount

      public int getRunningThreadCount()
      返回未被阻塞等待加入任务或其他受管理同步的工作线程数的估计。此方法可能高估运行线程的数量。
      返回:
      工作线程数
    • getActiveThreadCount

      public int getActiveThreadCount()
      返回当前正在窃取或执行任务的线程数的估计。此方法可能高估活动线程的数量。
      返回:
      活动线程数
    • isQuiescent

      public boolean isQuiescent()
      如果所有工作线程当前都处于空闲状态,则返回true。空闲工作线程是无法获取任务以执行的工作线程,因为没有可从其他线程窃取的任务,并且没有待提交到池中的任务。此方法是保守的;即使所有线程处于空闲状态,它可能不会立即返回true,但如果线程保持不活动,最终将返回true
      返回:
      如果所有线程当前都处于空闲状态,则返回true
    • getStealCount

      public long getStealCount()
      返回由提交者以外的线程执行的总完成任务数的估计。当池不安静时,报告的值低估了实际的窃取总数。此值可能对监视和调整fork/join程序有用:通常,窃取计数应足够高,以使线程保持繁忙,但又足够低,以避免跨线程的开销和争用。
      返回:
      窃取次数
    • getQueuedTaskCount

      public long getQueuedTaskCount()
      返回工作线程队列中当前持有的任务总数的估计(不包括尚未开始执行的提交到池中的任务)。此值仅是一个近似值,通过遍历池中的所有线程获得。此方法可能对调整任务粒度有用。
      返回:
      排队任务数
      参见:
    • getQueuedSubmissionCount

      public int getQueuedSubmissionCount()
      返回尚未开始执行的提交给此池的任务数量的估计。此方法可能需要与提交数量成比例的时间。
      返回:
      排队提交的数量
    • hasQueuedSubmissions

      public boolean hasQueuedSubmissions()
      如果有任何提交给此池尚未开始执行的任务,则返回true
      返回:
      如果有任何排队的提交,则返回true
    • pollSubmission

      protected ForkJoinTask<?> pollSubmission()
      如果有未执行的提交可用,则移除并返回下一个。此方法可能对于在具有多个池的系统中重新分配工作的此类的扩展很有用。
      返回:
      下一个提交,如果没有则返回null
    • drainTasksTo

      protected int drainTasksTo(Collection<? super ForkJoinTask<?>> c)
      从调度队列中移除所有可用的未执行提交和分叉任务,并将它们添加到给定的集合中,而不更改它们的执行状态。这些可能包括人为生成或包装的任务。此方法设计为仅在已知池处于静止状态时调用。在其他时间调用可能不会移除所有任务。在尝试将元素添加到集合c时遇到失败可能导致在抛出相关异常时元素既不在集合中也不在集合中,或者两者都在集合中。如果在操作进行时修改了指定的集合,则此操作的行为是未定义的。
      参数:
      c - 要转移元素的集合
      返回:
      转移的元素数量
    • toString

      public String toString()
      返回标识此池及其状态的字符串,包括运行状态、并行级别、工作线程和任务计数的指示。
      覆盖:
      toString 在类 Object
      返回:
      标识此池及其状态的字符串
    • shutdown

      public void shutdown()
      可能启动有序关闭,其中先前提交的任务将被执行,但不会接受新任务。如果这是commonPool(),则调用对执行状态没有影响,并且如果已关闭,则没有额外效果。在此方法执行过程中同时提交的任务可能会被拒绝或不被拒绝。
      抛出:
      SecurityException - 如果存在安全管理器并且调用方无权修改线程,因为它没有持有RuntimePermission("modifyThread")
    • shutdownNow

      public List<Runnable> shutdownNow()
      可能尝试取消和/或停止所有任务,并拒绝随后提交的所有任务。如果这是commonPool(),则调用对执行状态没有影响,并且如果已关闭,则没有额外效果。否则,在此方法执行过程中同时提交或执行的任务可能会被拒绝或不被拒绝。此方法取消现有和未执行的任务,以允许在存在任务依赖关系的情况下终止。因此,该方法始终返回一个空列表(与某些其他执行程序的情况不同)。
      返回:
      一个空列表
      抛出:
      SecurityException - 如果存在安全管理器并且调用方无权修改线程,因为它没有持有RuntimePermission("modifyThread")
    • isTerminated

      public boolean isTerminated()
      如果关闭后所有任务都已完成,则返回true
      返回:
      如果关闭后所有任务都已完成,则返回true
    • isTerminating

      public boolean isTerminating()
      如果终止过程已经开始但尚未完成,则返回true。此方法可能对调试很有用。在关闭后一段时间后返回true可能表明提交的任务已忽略或抑制中断,或者正在等待I/O,导致此执行程序无法正确终止。 (请参阅类ForkJoinTask的建议说明,指出任务通常不应包含阻塞操作。但如果确实包含,它们必须在中断时中止。)
      返回:
      如果正在终止但尚未终止,则返回true
    • isShutdown

      public boolean isShutdown()
      如果此池已关闭,则返回true
      返回:
      如果此池已关闭,则返回true
    • awaitTermination

      public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
      在关闭请求后,阻塞直到所有任务完成执行,或超时发生,或当前线程被中断,以先发生者为准。因为commonPool()直到程序关闭才终止,当应用于公共池时,此方法等效于awaitQuiescence(long, TimeUnit),但始终返回false
      参数:
      timeout - 等待的最长时间
      unit - 超时参数的时间单位
      返回:
      如果此执行程序终止,则返回true,如果超时在终止之前过期,则返回false
      抛出:
      InterruptedException - 在等待时被中断
    • awaitQuiescence

      public boolean awaitQuiescence(long timeout, TimeUnit unit)
      如果由在此池中运行的ForkJoinTask调用,则效果等同于ForkJoinTask.helpQuiesce()。否则,等待和/或尝试协助执行任务,直到此池isQuiescent()或指定的超时过去。
      参数:
      timeout - 等待的最长时间
      unit - 超时参数的时间单位
      返回:
      如果静止,则返回true;如果超时已过,则返回false
    • close

      public void close()
      除非这是commonPool(),否则启动有序关闭,其中先前提交的任务将被执行,但不会接受新任务,并等待直到所有任务完成执行并且执行程序已终止。

      如果已经终止,或者这是commonPool(),则此方法对执行没有影响,并且不会等待。否则,在等待时如果被中断,则此方法将停止所有正在执行的任务,就像调用shutdownNow()一样。然后继续等待,直到所有正在执行的任务都已完成。等待执行的任务不会被执行。在此方法返回之前,中断状态将被重新断言。

      抛出:
      SecurityException - 如果存在安全管理器并且关闭此ExecutorService可能操作调用方无权修改的线程,因为它没有持有RuntimePermission("modifyThread"),或者安全管理器的checkAccess方法拒绝访问。
      自:
      19
    • managedBlock

      public static void managedBlock(ForkJoinPool.ManagedBlocker blocker) throws InterruptedException
      运行给定的可能会阻塞的任务。当在ForkJoinPool中运行时,此方法可能会安排激活备用线程,以确保在当前线程在blocker.block()中被阻塞时保证足够的并行性。

      此方法重复调用blocker.isReleasable()blocker.block(),直到其中一个方法返回true。每次调用blocker.block()之前都会调用返回falseblocker.isReleasable()

      如果不在ForkJoinPool中运行,则此方法在行为上等同于

       
       while (!blocker.isReleasable())
         if (blocker.block())
           break;
      如果在ForkJoinPool中运行,则可能首先扩展池以确保在调用blocker.block()期间有足够的并行性可用。
      参数:
      blocker - 阻塞任务
      抛出:
      InterruptedException - 如果blocker.block()这样做