- 类型参数:
-
V- 任务结果的类型
- 所有实现的接口:
-
Serializable,Future<V>
- 直接已知的子类:
-
CountedCompleter,RecursiveAction,RecursiveTask
ForkJoinPool内运行的抽象基类。 ForkJoinTask是一个比普通线程轻量得多的实体。大量的任务和子任务可以由ForkJoinPool中的少量实际线程托管,但需要付出一些使用限制的代价。
当"主" ForkJoinTask被明确提交到ForkJoinPool,或者如果尚未参与ForkJoin计算,则通过ForkJoinPool.commonPool()中的fork()、invoke()或相关方法开始执行。一旦开始,它通常会启动其他子任务。正如这个类的名称所示,许多使用ForkJoinTask的程序仅使用fork()和join()方法,或者派生方法,如invokeAll。然而,这个类还提供了许多其他方法,可以在高级用法中发挥作用,以及允许支持新形式的fork/join处理的扩展机制。
ForkJoinTask是Future的轻量形式。 ForkJoinTask的效率源于一组限制(只有部分静态可强制执行),反映了它们作为计算任务计算纯函数或操作纯粹隔离对象的主要用途。主要的协调机制是fork(),安排异步执行,和join(),在任务结果计算完成之前不会继续。计算应该尽量避免synchronized方法或块,并且应该最小化除了加入其他任务或使用与fork/join调度协作的同步器(例如Phasers)之外的其他阻塞同步。可分割的任务也不应执行阻塞I/O,并且应该理想地访问与其他运行任务访问的变量完全独立的变量。这些准则通过不允许抛出像IOExceptions这样的已检查异常来松散执行。然而,计算仍然可能遇到未检查的异常,这些异常会被重新抛出给试图加入它们的调用者。这些异常可能还包括由于内部资源耗尽(例如无法分配内部任务队列)而导致的RejectedExecutionException。重新抛出的异常的行为与常规异常相同,但在可能的情况下,包含发起计算的线程和实际遇到异常的线程的堆栈跟踪(例如使用ex.printStackTrace()显示的堆栈跟踪);最少只包含后者。
可以定义和使用可能会阻塞的ForkJoinTasks,但这样做需要进一步考虑:(1)很少或根本没有其他任务的完成应取决于在外部同步或I/O上阻塞的任务。从不加入的事件式异步任务(例如,那些子类化CountedCompleter的任务)通常属于这一类。 (2) 为了最小化资源影响,任务应该很小;理想情况下只执行(可能)阻塞的操作。 (3) 除非使用ForkJoinPool.ManagedBlocker API,或者可能被阻塞的任务数量已知少于池的ForkJoinPool.getParallelism()级别,否则池无法保证有足够的线程可用以确保进展或良好性能。
等待任务完成并提取结果的主要方法是join(),但还有几个变体: Future.get()方法支持可中断和/或定时等待完成,并使用Future约定报告结果。方法invoke()在语义上等同于fork(); join(),但始终尝试在当前线程中开始执行。这些方法的“安静”形式不提取结果或报告异常。当一组任务正在执行,并且需要延迟处理结果或异常直到所有任务完成时,这些方法可能很有用。方法invokeAll(有多个版本可用)执行最常见的并行调用形式:分叉一组任务并将它们全部加入。
在最典型的用法中,fork-join对像并行递归函数的调用(fork)和返回(join)。与其他形式的递归调用一样,返回(join)应该从最内部开始执行。例如,a.fork(); b.fork(); b.join(); a.join();可能比在b之前加入a要高效得多。
任务的执行状态可以在几个详细级别查询:如果任务以任何方式完成(包括任务在没有执行的情况下被取消的情况),则isDone()为true;如果任务在没有取消或遇到异常的情况下完成,则isCompletedNormally()为true;如果任务被取消,则isCancelled()为true(在这种情况下,getException(int)返回一个CancellationException);如果任务被取消或遇到异常,则isCompletedAbnormally()为true,在这种情况下,getException(int)将返回遇到的异常或CancellationException。
ForkJoinTask类通常不直接被子类化。相反,您应该为支持特定风格的fork/join处理的抽象类之一进行子类化,通常对于大多数不返回结果的计算使用RecursiveAction,对于返回结果的计算使用RecursiveTask,对于完成操作触发其他操作的操作使用CountedCompleter。通常,具体的ForkJoinTask子类声明包含其参数的字段,在构造函数中建立,并定义一个compute方法,该方法以某种方式使用此基类提供的控制方法。
join()及其变体仅在完成依赖关系是无环的情况下适用;也就是说,并行计算可以描述为有向无环图(DAG)。否则,执行可能会遇到一种形式的死锁,因为任务循环等待彼此。但是,这个框架支持其他方法和技术(例如使用Phaser、helpQuiesce()和complete(V))可能对构建不是静态结构为DAG的问题的自定义子类有用。为了支持这种用法,可以使用setForkJoinTaskTag(short)或compareAndSetForkJoinTaskTag(short, short)原子地为ForkJoinTask打上一个short值,并使用getForkJoinTaskTag()进行检查。ForkJoinTask实现不使用这些protected方法或标记,但它们可能在构建专门的子类时有用。例如,并行图遍历可以使用提供的方法避免重新访问已处理的节点/任务。 (标记的方法名称部分冗长,以鼓励定义反映其使用模式的方法。)
大多数基本支持方法都是final的,以防止覆盖与底层轻量级任务调度框架密切相关的实现。创建新的基本fork/join处理样式的开发人员应该最小化实现protected方法exec()、setRawResult(V)和getRawResult(),同时引入一个可以在其子类中实现的抽象计算方法,可能依赖于此类提供的其他protected方法。
ForkJoinTasks应该执行相对较小的计算量。大型任务应该通过递归分解拆分为较小的子任务。作为一个非常粗略的经验法则,一个任务应该执行超过100个且少于10000个基本计算步骤,并且应该避免无限循环。如果任务太大,则并行性无法提高吞吐量。如果太小,则内存和内部任务维护开销可能会压倒处理。
这个类为Runnable和Callable提供了adapt方法,当混合执行ForkJoinTasks和其他类型的任务时可能会有用。当所有任务都是这种形式时,考虑使用在asyncMode中构造的池。
ForkJoinTasks是Serializable的,这使它们可以在诸如远程执行框架之类的扩展中使用。在执行期间,只有在执行之前或之后,而不是在执行过程中,才依赖于序列化。
- 自从:
- 1.7
- 参见:
-
Nested Class Summary
Nested classes/interfaces declared in interface java.util.concurrent.Future
Future.State -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic ForkJoinTask<?> static <T> ForkJoinTask<T> static <T> ForkJoinTask<T> static <T> ForkJoinTask<T> adaptInterruptible(Callable<? extends T> callable) booleancancel(boolean mayInterruptIfRunning) 尝试取消执行此任务。final booleancompareAndSetForkJoinTaskTag(short expect, short update) 原子地有条件地设置此任务的标记值。void完成此任务,如果尚未中止或取消,则将给定值作为后续调用join和相关操作的结果返回。void异常地完成此任务,如果尚未中止或取消,则导致在join和相关操作时抛出给定异常。protected abstract booleanexec()立即执行此任务的基本操作,并在从此方法返回时,保证此任务已完成时返回true。final ForkJoinTask<V> fork()安排在当前任务正在运行的池中异步执行此任务,如果适用,或者使用ForkJoinPool.commonPool(),如果不在inForkJoinPool()中。final Vget()等待计算完成,然后检索其结果。final V等待最多给定时间,直到计算完成,然后检索其结果(如果可用)。final Throwable返回基本计算抛出的异常,如果取消则返回CancellationException,如果没有或方法尚未完成则返回null。final short返回此任务的标记。static ForkJoinPoolgetPool()返回托管当前线程的池,如果当前线程在任何ForkJoinPool之外执行,则返回null。static int返回当前工作线程已分叉但尚未执行的任务数量的估计值。abstract V返回将由join()返回的结果,即使此任务异常完成,如果此任务未知是否已完成,则返回null。static int返回本地排队任务比其他可能窃取它们的工作线程多的估计值,如果此线程不在ForkJoinPool中操作,则返回零。static void可能执行任务,直到托管当前任务的池静止。static boolean如果当前线程作为ForkJoinPool计算执行,则返回true。final Vinvoke()开始执行此任务,必要时等待其完成,并返回其结果,如果底层计算如此,则抛出(未检查的)RuntimeException或Error。static <T extends ForkJoinTask<?>>
Collection<T> invokeAll(Collection<T> tasks) 分叉指定集合中的所有任务,在每个任务的isDone保持或遇到(未检查的)异常时返回,此时重新抛出异常。static voidinvokeAll(ForkJoinTask<?>... tasks) 分叉给定任务,在每个任务的isDone保持或遇到(未检查的)异常时返回,此时重新抛出异常。static voidinvokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) 分叉给定任务,在每个任务的isDone保持或遇到(未检查的)异常时返回,此时重新抛出异常。final boolean如果此任务在正常完成之前被取消,则返回true。final boolean如果此任务抛出异常或被取消,则返回true。final boolean如果此任务在没有抛出异常并且未被取消的情况下完成,则返回true。final booleanisDone()如果此任务已完成,则返回true。final Vjoin()返回计算结果,当它完成时。protected static ForkJoinTask<?> 返回由当前线程排队但尚未执行的任务,如果立即可用则返回,但不取消或执行。protected static ForkJoinTask<?> 如果当前线程在ForkJoinPool中操作,则取消并返回由当前线程排队但尚未执行的下一个任务,而不执行。protected static ForkJoinTask<?> 如果当前线程在ForkJoinPool中操作,则取消并返回由池外部提交给池的任务,如果可用则返回。protected static ForkJoinTask<?> pollTask()如果当前线程在ForkJoinPool中操作,则取消并返回由当前线程排队但尚未执行的下一个任务,如果可用则返回,如果不可用则返回由其他线程分叉的任务(如果可用)。final void正常完成此任务,而不设置值。final void开始执行此任务,必要时等待其完成,而不返回其结果或抛出异常。final void加入此任务,而不返回其结果或抛出异常。final booleanquietlyJoin(long timeout, TimeUnit unit) 尝试加入此任务,如果在给定超时之前完成(可能异常),并且当前线程未被中断,则返回true。final booleanquietlyJoinUninterruptibly(long timeout, TimeUnit unit) 尝试加入此任务,如果在给定超时之前完成(可能异常),则返回true。void重置此任务的内部簿记状态,允许随后的fork。final shortsetForkJoinTaskTag(short newValue) 原子地设置此任务的标记值并返回旧值。protected abstract voidsetRawResult(V value) 强制将给定值作为结果返回。boolean尝试取消此任务的调度。Methods declared in class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods declared in interface java.util.concurrent.Future
exceptionNow, resultNow, state
-
Constructor Details
-
ForkJoinTask
public ForkJoinTask()子类调用的构造函数。
-
-
Method Details
-
fork
安排在当前任务正在运行的池中异步执行此任务,如果适用,或者使用ForkJoinPool.commonPool(),如果不在inForkJoinPool()中。虽然不一定强制执行,但多次分叉任务除非已完成并重新初始化,否则是使用错误。除非先调用join()或相关方法,或调用isDone()返回true,否则对此任务的状态或其操作的任何数据的后续修改不一定被任何线程一致地观察到。- 返回:
-
this,以简化使用
-
join
返回计算结果,当它完成时。此方法与get()不同之处在于异常完成会导致RuntimeException或Error,而不是ExecutionException,并且调用线程的中断不会导致方法突然通过抛出InterruptedException返回。- 返回:
- 计算的结果
-
invoke
开始执行此任务,必要时等待其完成,并返回其结果,如果底层计算如此,则抛出(未检查的)RuntimeException或Error。- 返回:
- 计算的结果
-
invokeAll
分叉给定任务,在每个任务的isDone保持或遇到(未检查的)异常时返回,此时重新抛出异常。如果多个任务遇到异常,则此方法抛出其中任何一个异常。如果任何任务遇到异常,则其他任务可能被取消。但是,个别任务的执行状态在异常返回时不能保证。可以使用getException()和相关方法获取每个任务的状态,以检查它们是否已被取消,正常完成或异常完成,或未处理。- 参数:
-
t1- 第一个任务 -
t2- 第二个任务 - 抛出:
-
NullPointerException- 如果任何任务为null
-
invokeAll
分叉给定任务,在每个任务的isDone保持或遇到(未检查的)异常时返回,此时重新抛出异常。如果多个任务遇到异常,则此方法抛出其中任何一个异常。如果任何任务遇到异常,则其他任务可能被取消。但是,个别任务的执行状态在异常返回时不能保证。可以使用getException()和相关方法获取每个任务的状态,以检查它们是否已被取消,正常完成或异常完成,或未处理。- 参数:
-
tasks- 任务 - 抛出:
-
NullPointerException- 如果任何任务为null
-
invokeAll
分叉指定集合中的所有任务,在每个任务的isDone保持或遇到(未检查的)异常时返回,此时重新抛出异常。如果多个任务遇到异常,则此方法抛出其中任何一个异常。如果任何任务遇到异常,则其他任务可能被取消。但是,个别任务的执行状态在异常返回时不能保证。可以使用getException()和相关方法获取每个任务的状态,以检查它们是否已被取消,正常完成或异常完成,或未处理。- 类型参数:
-
T- 任务返回值的类型 - 参数:
-
tasks- 任务的集合 - 返回:
- 任务参数,以简化使用
- 抛出:
-
NullPointerException- 如果任务或任何元素为null
-
cancel
public boolean cancel(boolean mayInterruptIfRunning) 尝试取消此任务的执行。如果任务已经完成或由于其他原因无法取消,则此尝试将失败。如果成功,并且在调用cancel时此任务尚未启动,则此任务的执行将被抑制。在此方法成功返回后,除非有介入调用reinitialize(),否则对isCancelled()、isDone()和cancel的后续调用将返回true,对join()和相关方法的调用将导致CancellationException。此方法可以在子类中重写,但如果这样做,仍必须确保这些属性保持不变。特别是,
cancel方法本身不得抛出异常。此方法旨在由其他任务调用。要终止当前任务,您可以从其计算方法中返回或抛出未经检查的异常,或调用
completeExceptionally(Throwable)。 -
isDone
public final boolean isDone()从接口复制的描述:Future如果此任务已完成,则返回true。完成可能是由于正常终止、异常或取消 - 在所有这些情况下,此方法将返回true。 -
isCancelled
public final boolean isCancelled()从接口复制的描述:Future如果此任务在正常完成之前被取消,则返回true。- 指定者:
-
isCancelled在接口Future<V> - 返回:
-
如果此任务在完成之前被取消,则为
true
-
isCompletedAbnormally
public final boolean isCompletedAbnormally()如果此任务抛出异常或被取消,则返回true。- 返回:
-
如果此任务抛出异常或被取消,则为
true
-
isCompletedNormally
public final boolean isCompletedNormally()如果此任务在没有抛出异常并且未被取消的情况下完成,则返回true。- 返回:
-
如果此任务在没有抛出异常并且未被取消的情况下完成,则为
true
-
getException
返回基本计算抛出的异常,如果取消则返回CancellationException,如果没有异常或方法尚未完成则返回null。- 返回:
-
异常,如果没有则返回
null
-
completeExceptionally
异常完成此任务,并且如果尚未中止或取消,则导致在join和相关操作中抛出给定的异常。此方法可用于在异步任务中引发异常,或强制完成否则不会正常完成的任务。不鼓励在其他情况下使用此方法。此方法可重写,但重写版本必须调用super实现以保持保证。- 参数:
-
ex- 要抛出的异常。如果此异常不是RuntimeException或Error,则实际抛出的异常将是带有原因ex的RuntimeException。
-
complete
完成此任务,并且如果尚未中止或取消,则将给定值作为后续调用join和相关操作的结果返回。此方法可用于为异步任务提供结果,或为否则不会正常完成的任务提供替代处理。不鼓励在其他情况下使用此方法。此方法可重写,但重写版本必须调用super实现以保持保证。- 参数:
-
value- 此任务的结果值
-
quietlyComplete
public final void quietlyComplete()正常完成此任务而不设置值。由setRawResult(V)(或默认情况下为null)建立的最新值将作为后续调用join和相关操作的结果返回。- 自1.8起:
- 1.8
-
get
等待计算完成,然后检索其结果。- 指定者:
-
get在接口Future<V> - 返回:
- 计算的结果
- 抛出:
-
CancellationException- 如果计算被取消 -
ExecutionException- 如果计算抛出异常 -
InterruptedException- 如果当前线程不是ForkJoinPool的成员并且在等待时被中断
-
get
public final V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 在最多给定时间内等待计算完成,然后检索其结果(如果可用)。- 指定者:
-
get在接口Future<V> - 参数:
-
timeout- 等待的最长时间 -
unit- 超时参数的时间单位 - 返回:
- 计算的结果
- 抛出:
-
CancellationException- 如果计算被取消 -
ExecutionException- 如果计算抛出异常 -
InterruptedException- 如果当前线程不是ForkJoinPool的成员并且在等待时被中断 -
TimeoutException- 如果等待超时
-
quietlyJoin
public final void quietlyJoin()加入此任务,而不返回其结果或抛出其异常。当处理任务集合时,一些任务已被取消或已知已中止时,此方法可能很有用。 -
quietlyInvoke
public final void quietlyInvoke()开始执行此任务,并在必要时等待其完成,而不返回其结果或抛出其异常。 -
quietlyJoin
尝试加入此任务,在给定超时之前完成(可能异常),并且当前线程未被中断时返回true。- 参数:
-
timeout- 等待的最长时间 -
unit- 超时参数的时间单位 - 返回:
-
如果此任务已完成,则为
true - 抛出:
-
InterruptedException- 如果当前线程在等待时被中断 - 自19起:
- 19
-
quietlyJoinUninterruptibly
尝试加入此任务,在给定超时之前完成(可能异常)时返回true。- 参数:
-
timeout- 等待的最长时间 -
unit- 超时参数的时间单位 - 返回:
-
如果此任务已完成,则为
true - 自19起:
- 19
-
helpQuiesce
public static void helpQuiesce()可能执行任务,直到托管当前任务的池静止。此方法可能在设计中有用,其中许多任务被分叉,但没有明确加入,而是执行它们直到所有任务都被处理。 -
reinitialize
public void reinitialize()重置此任务的内部簿记状态,允许随后的fork。此方法允许重复重用此任务,但仅当此任务从未被分叉或已被分叉,然后完成并且此任务的所有未完成的加入也已完成时才能重用。在任何其他使用条件下的效果不能保证。在循环中执行预先构建的子任务树时,此方法可能很有用。完成此方法后,
isDone()报告false,getException()报告null。但是,getRawResult返回的值不受影响。要清除此值,可以调用setRawResult(null)。 -
getPool
返回托管当前线程的池,如果当前线程在任何ForkJoinPool之外执行,则返回null。仅当
inForkJoinPool()返回false时,此方法返回null。- 返回:
-
如果没有则返回池,否则返回
null
-
inForkJoinPool
public static boolean inForkJoinPool()如果当前线程是作为ForkJoinPool计算执行的,则返回 true。- 返回:
-
如果当前线程是作为ForkJoinPool计算执行的
,则返回 true,否则返回false
-
tryUnfork
public boolean tryUnfork()尝试取消此任务的执行。如果此任务是当前线程最近fork的任务,并且尚未在另一个线程中执行,则此方法通常(但不保证)会成功。当安排任务的替代本地处理可能有用时,此方法可能很有用,这些任务本应被窃取,但实际上并未被窃取。- 返回:
-
如果取消fork,则返回
true
-
getQueuedTaskCount
public static int getQueuedTaskCount()返回当前工作线程fork但尚未执行的任务数量的估计值。此值可能对是否fork其他任务做出启发式决策很有用。- 返回:
- 任务数量
-
getSurplusQueuedTaskCount
public static int getSurplusQueuedTaskCount()返回当前工作线程持有的本地排队任务比其他可能窃取这些任务的工作线程多的估计值,如果此线程不在ForkJoinPool中操作,则返回零。此值可能对是否fork其他任务做出启发式决策很有用。在许多ForkJoinTasks的用法中,在稳定状态下,每个工作线程应该努力保持一小部分常数剩余任务(例如3),并且如果超过此阈值,则在本地处理计算。- 返回:
- 剩余任务数量,可能为负数
-
getRawResult
返回将由join()返回的结果,即使此任务异常完成,如果不知道此任务是否已完成,则返回null。此方法旨在帮助调试,以及支持扩展。不鼓励在任何其他上下文中使用此方法。- 返回:
-
结果,如果未完成则返回
null
-
setRawResult
强制将给定值作为结果返回。此方法旨在支持扩展,通常不应调用。- 参数:
-
value- 值
-
exec
protected abstract boolean exec()立即执行此任务的基本操作,并在从此方法返回时如果此任务已保证完成则返回true。否则,此方法可能返回false,表示此任务不一定完成(或不知道是否完成),例如在需要显式调用完成方法的异步操作中。此方法还可能抛出(未检查的)异常以指示异常退出。此方法旨在支持扩展,通常不应调用。- 返回:
-
如果此任务已知正常完成则返回
true
-
peekNextLocalTask
返回但不取消或执行由当前线程排队但尚未执行的任务,如果立即可用。不能保证此任务实际上将被轮询或执行。反之,即使存在任务,此方法也可能返回null,但无法在不与其他线程竞争的情况下访问。此方法主要用于支持扩展,否则不太可能有用。- 返回:
-
下一个任务,如果没有则返回
null
-
pollNextLocalTask
如果当前线程在ForkJoinPool中操作,则取消并返回由当前线程排队但尚未执行的下一个任务,而不执行。此方法主要用于支持扩展,否则不太可能有用。- 返回:
-
下一个任务,如果没有则返回
null
-
pollTask
如果当前线程在ForkJoinPool中操作,则取消并返回由当前线程排队但尚未执行的下一个任务,如果可用,则返回,如果不可用,则返回由其他线程fork的任务(如果可用)。可用性可能是瞬时的,因此null结果不一定意味着此任务所在的池处于静止状态。此方法主要用于支持扩展,否则不太可能有用。- 返回:
-
任务,如果没有则返回
null
-
pollSubmission
如果当前线程在ForkJoinPool中操作,则取消并返回由池外部提交的任务,如果可用则返回,可用性可能是瞬时的,因此null结果不一定意味着池处于静止状态。此方法主要用于支持扩展,否则不太可能有用。- 返回:
-
任务,如果没有则返回
null - 自:
- 9
-
getForkJoinTaskTag
public final short getForkJoinTaskTag()返回此任务的标记。- 返回:
- 此任务的标记
- 自:
- 1.8
-
setForkJoinTaskTag
public final short setForkJoinTaskTag(short newValue) 原子地设置此任务的标记值并返回旧值。- 参数:
-
newValue- 新的标记值 - 返回:
- 标记的先前值
- 自:
- 1.8
-
compareAndSetForkJoinTaskTag
public final boolean compareAndSetForkJoinTaskTag(short expect, short update) 原子地有条件地设置此任务的标记值。标记可以用作在操作图的任务上操作时的访问标记,例如在处理之前检查:if (task.compareAndSetForkJoinTaskTag((short)0, (short)1)),否则退出,因为节点已被访问。- 参数:
-
expect- 期望的标记值 -
update- 新的标记值 - 返回:
-
如果成功,则返回
true;即当前值等于expect并且已更改为update。 - 自:
- 1.8
-
adapt
- 参数:
-
runnable- 可运行的操作 - 返回:
- 任务
-
adapt
- 类型参数:
-
T- 结果的类型 - 参数:
-
runnable- 可运行的操作 -
result- 完成时的结果 - 返回:
- 任务
-
adapt
- 类型参数:
-
T- 可调用结果的类型 - 参数:
-
callable- 可调用操作 - 返回:
- 任务
-
adaptInterruptible
返回一个新的ForkJoinTask,执行给定Callable的call方法作为其操作,并在join()时返回其结果,将遇到的任何已检查异常转换为RuntimeException。此外,使用mayInterruptIfRunning true调用cancel将尝试中断执行任务的线程。- 类型参数:
-
T- 可调用结果的类型 - 参数:
-
callable- 可调用操作 - 返回:
- 任务
- 自:
- 19
-