package java.util.concurrent;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.RandomAccess;
import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantLock;
import java.lang.reflect.Constructor;
/**
* 在ForkJoinPool内运行的任务的抽象基类。
* Abstract base class for tasks that run within a {@link ForkJoinPool}.
* ForkJoinTask是一个线程实体,其重量比普通线程轻得多。
* A {@code ForkJoinTask} is a thread-like entity that is much
* lighter weight than a normal thread. Huge numbers of tasks and
* 在一个ForkJoinPool中,大量的任务和子任务可能由少量的实际线程来承载,
* 这是以一些使用限制为代价的。
* subtasks may be hosted by a small number of actual threads in a
* ForkJoinPool, at the price of some usage limitations.
*
* 一个“main”{@code ForkJoinTask}在显式提交给{@link ForkJoinPool}时开始执行,
* 或者,如果还没有参与到ForkJoin计算中,则通过{@link #fork}、{@link #invoke}或
* 相关方法在{@link ForkJoinPool#commonPool()}中开始执行。
* <p>A "main" {@code ForkJoinTask} begins execution when it is
* explicitly submitted to a {@link ForkJoinPool}, or, if not already
* engaged in a ForkJoin computation, commenced in the {@link
* ForkJoinPool#commonPool()} via {@link #fork}, {@link #invoke}, or
* 一旦启动,它通常会依次启动其他子任务。
* related methods. Once started, it will usually in turn start other
* 从这个类的名称可以看出,许多使用{@code ForkJoinTask}的程序只使用{@link #fork}和{@link #join}方法,
* 或者衍生的方法,如{@link #invokeAll(ForkJoinTask…) invokeAll}。
* subtasks. As indicated by the name of this class, many programs
* using {@code ForkJoinTask} employ only methods {@link #fork} and
* {@link #join}, or derivatives such as {@link
* #invokeAll(ForkJoinTask...) invokeAll}.
* 但是,这个类还提供了许多其他方法,可以在高级用法中发挥作用,以及支持新形式的fork/join处理的扩展机制。
* However, this class also
* provides a number of other methods that can come into play in
* advanced usages, as well as extension mechanics that allow support
* of new forms of fork/join processing.
*
* {@code ForkJoinTask}是{@link Future}的轻量级形式。
* <p>A {@code ForkJoinTask} is a lightweight form of {@link Future}.
* {@code ForkJoinTask}的效率源于一组限制(只是部分静态强制执行),
* 反映其主要用途为计算任务计算纯函数或操作纯粹孤立的对象。
* The efficiency of {@code ForkJoinTask}s stems from a set of
* restrictions (that are only partially statically enforceable)
* reflecting their main use as computational tasks calculating pure
* functions or operating on purely isolated objects. The primary
* 主要的协调机制是{@link #fork},它安排异步执行;{@link #join},它直到计算完任务的结果才继续执行。
* coordination mechanisms are {@link #fork}, that arranges
* asynchronous execution, and {@link #join}, that doesn't proceed
* until the task's result has been computed.
* 理想情况下,计算应该避免{@code synchronized}方法或块,并且除了连接其他任务或使用与fork/join调度协
* 作的同步器(如“Phasers”)之外,还应该最小化其他阻塞同步。
* Computations should
* ideally avoid {@code synchronized} methods or blocks, and should
* minimize other blocking synchronization apart from joining other
* tasks or using synchronizers such as Phasers that are advertised to
* cooperate with fork/join scheduling. Subdividable tasks should also
* 可细分的任务也不应该执行阻塞I/O,理想情况下应该访问完全独立于其他正在运行的任务所访问的变量。
* not perform blocking I/O, and should ideally access variables that
* are completely independent of those accessed by other running
* 通过不允许抛出{@code IOExceptions}等检查过的异常,可以松散地执行这些准则。
* tasks. These guidelines are loosely enforced by not permitting
* checked exceptions such as {@code IOExceptions} to be
* 然而,计算可能仍然会遇到未检查的异常,这些异常会被重新抛出给试图加入它们的调用者。
* thrown. However, computations may still encounter unchecked
* exceptions, that are rethrown to callers attempting to join
* 这些异常还可能包括{@link RejectedExecutionException},它源于内部资源的耗尽,
* 比如分配内部任务队列的失败。
* them. These exceptions may additionally include {@link
* RejectedExecutionException} stemming from internal resource
* exhaustion, such as failure to allocate internal task
* 重新抛出的异常与常规异常的行为方式相同,但在可能的情况下,包含堆栈跟踪
* (例如使用{@code ex.printStackTrace()}显示启动计算的线程和实际遇到异常的线程;
* 至少是后者。
* queues. Rethrown exceptions behave in the same way as regular
* exceptions, but, when possible, contain stack traces (as displayed
* for example using {@code ex.printStackTrace()}) of both the thread
* that initiated the computation as well as the thread actually
* encountering the exception; minimally only the latter.
*
* 定义和使用可能阻塞的forkjointask是可能的,但这么做需要进一步考虑三个事项:
* (1)如果任何其他任务应该依赖于阻塞外部同步或I / O的任务,则完成很少。
* 事件风格的异步任务从未加入(例如,这些子类CountedCompleter )通常属于此类别。
* <p>It is possible to define and use ForkJoinTasks that may block,
* but doing do requires three further considerations: (1) Completion
* of few if any <em>other</em> tasks should be dependent on a task
* that blocks on external synchronization or I/O. Event-style async
* tasks that are never joined (for example, those subclassing {@link
* CountedCompleter}) often fall into this category.
* (2)为了减少资源影响,任务应该小;理想情况下,只执行(可能的)阻塞操作。
* (2) To minimize
* resource impact, tasks should be small; ideally performing only the
* (possibly) blocking action.
* (3)除非使用{@link ForkJoinPool.ManagedBlocker} API,或者已知可能被阻塞的
* 任务数小于池的{@link ForkJoinPool#getParallelism}级别,否则池不能保证有足够的线程可用,
* 以确保进程或性能良好。
* (3) Unless the {@link
* ForkJoinPool.ManagedBlocker} API is used, or the number of possibly
* blocked tasks is known to be less than the pool's {@link
* ForkJoinPool#getParallelism} level, the pool cannot guarantee that
* enough threads will be available to ensure progress or good
* performance.
*
* 等待完成和提取任务结果的主要方法是{@link #join},但是有几个变体:
* <p>The primary method for awaiting completion and extracting
* results of a task is {@link #join}, but there are several variants:
* {@link Future#get}方法支持可中断 和/或 定时等待完成并使用{@code Future}约定报告结果。
* The {@link Future#get} methods support interruptible and/or timed
* waits for completion and report results using {@code Future}
* conventions.
* 方法{@link #invoke}在语义上等价于{@code fork();}但总是试图在当前线程中开始执行。
* Method {@link #invoke} is semantically
* equivalent to {@code fork(); join()} but always attempts to begin
* execution in the current thread. The "<em>quiet</em>" forms of
* 这些方法的“<em>quiet</em>”形式不提取结果或报告异常。
* these methods do not extract results or report exceptions. These
* 当执行一组任务时,这些可能很有用,并且需要将结果或异常的处理延迟到全部完成时。
* may be useful when a set of tasks are being executed, and you need
* to delay processing of results or exceptions until all complete.
* 方法{@code invokeAll}(在多个版本中可用)执行最常见的并行调用形式:
* forking一组任务并将它们全部joining起来。
* Method {@code invokeAll} (available in multiple versions)
* performs the most common form of parallel invocation: forking a set
* of tasks and joining them all.
*
* 在大多数典型的用法中,fork-join对的作用类似于一个调用(fork)和一个并行递归函数的返回(join)。
* <p>In the most typical usages, a fork-join pair act like a call
* (fork) and return (join) from a parallel recursive function. As is
* 与其他形式的递归调用一样,返回(连接)应该是最内层的。
* the case with other forms of recursive calls, returns (joins)
* should be performed innermost-first. For example, {@code a.fork();
* 例如,{@code a.fork();b.fork ();b.join ();a.join();}可能比在{@code b}之前加入{@code a}要有效得多。
* b.fork(); b.join(); a.join();} is likely to be substantially more
* efficient than joining {@code a} before {@code b}.
*
* 任务的执行状态可以在几个层次上详细查询:
* <p>The execution status of tasks may be queried at several levels
* 如果任务以任何方式完成(包括在没有执行的情况下取消任务),则{@link #isDone}为真;
* of detail: {@link #isDone} is true if a task completed in any way
* (including the case where a task was cancelled without executing);
* 如果任务在没有取消或遇到异常的情况下完成,则{@link # iscompletednormal}为真;
* {@link #isCompletedNormally} is true if a task completed without
* cancellation or encountering an exception; {@link #isCancelled} is
* 如果任务被取消,则{@link #isCancelled}为真(在这种情况下,{@link #getException}
* 返回一个{@link java.util.concurrent.CancellationException});
* true if the task was cancelled (in which case {@link #getException}
* returns a {@link java.util.concurrent.CancellationException}); and
* 如果任务被取消或遇到异常,则{@link #isCompletedAbnormally}为真,在这种情况下
* {@link #getException}将返回遇到的异常或{@link java.util.concurrent.CancellationException}。
* {@link #isCompletedAbnormally} is true if a task was either
* cancelled or encountered an exception, in which case {@link
* #getException} will return either the encountered exception or
* {@link java.util.concurrent.CancellationException}.
*
* ForkJoinTask类通常不直接子类化。
* <p>The ForkJoinTask class is not usually directly subclassed.
* 相反,您可以子类化一个抽象类,它支持一种特定的fork/join处理风格,
* 通常{@link RecursiveAction}用于不返回结果的大多数计算,{@link RecursiveTask}
* 用于返回结果的计算,{@link CountedCompleter}用于那些完成的操作触发其他操作的计算。
* Instead, you subclass one of the abstract classes that support a
* particular style of fork/join processing, typically {@link
* RecursiveAction} for most computations that do not return results,
* {@link RecursiveTask} for those that do, and {@link
* CountedCompleter} for those in which completed actions trigger
* other actions.
* 通常,一个具体的ForkJoinTask子类声明包含其参数的字段,在构造函数中建立,
* 然后定义一个{@code compute}方法,以某种方式使用这个基类提供的控制方法。
* Normally, a concrete ForkJoinTask subclass declares
* fields comprising its parameters, established in a constructor, and
* then defines a {@code compute} method that somehow uses the control
* methods supplied by this base class.
*
* 方法{@link #join}及其变体仅适用于完成依赖项为非循环的情况;也就是说,
* 并行计算可以描述为一个有向无环图(DAG)。
* <p>Method {@link #join} and its variants are appropriate for use
* only when completion dependencies are acyclic; that is, the
* parallel computation can be described as a directed acyclic graph
* (DAG).
* 否则,在任务循环地相互等待时,执行可能会遇到某种形式的死锁。
* Otherwise, executions may encounter a form of deadlock as
* tasks cyclically wait for each other.
* 但是,这个框架支持其他方法和技术(例如使用{@link Phaser}、
* {@link #helpQuiesce}和{@link #complete}),这些方法和技术可以用于为
* 非静态结构为DAGs的问题构造自定义子类。
* However, this framework
* supports other methods and techniques (for example the use of
* {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that
* may be of use in constructing custom subclasses for problems that
* are not statically structured as DAGs.
* 为了支持这种用法,可以使用{@link #setForkJoinTaskTag}或{@link #compareAndSetForkJoinTaskTag}
* 原子标记一个{@code short}值,并使用{@link #getForkJoinTaskTag}检查。
* To support such usages, a
* ForkJoinTask may be atomically <em>tagged</em> with a {@code short}
* value using {@link #setForkJoinTaskTag} or {@link
* #compareAndSetForkJoinTaskTag} and checked using {@link
* #getForkJoinTaskTag}.
* ForkJoinTask实现没有为任何目的使用这些{@code protected}方法或标记,
* 但它们可能用于特殊子类的构造。
* The ForkJoinTask implementation does not use
* these {@code protected} methods or tags for any purpose, but they
* may be of use in the construction of specialized subclasses. For
* 例如,并行图遍历可以使用提供的方法来避免重新访问已经处理过的节点/任务。
* example, parallel graph traversals can use the supplied methods to
* avoid revisiting nodes/tasks that have already been processed.
* (用于标记的方法名称非常庞大,部分原因是为了鼓励对反映其使用模式的方法进行定义。)
* (Method names for tagging are bulky in part to encourage definition
* of methods that reflect their usage patterns.)
*
* 大多数基本支持方法是{@code final},以防止覆盖本质上与底层轻量级任务调度框架相关的实现。
* <p>Most base support methods are {@code final}, to prevent
* overriding of implementations that are intrinsically tied to the
* underlying lightweight task scheduling framework. Developers
* creating new basic styles of fork/join processing should minimally
* implement {@code protected} methods {@link #exec}, {@link
* #setRawResult}, and {@link #getRawResult}, while also introducing
* an abstract computational method that can be implemented in its
* subclasses, possibly relying on other {@code protected} methods
* provided by this class.
*
* <p>ForkJoinTasks should perform relatively small amounts of
* computation. Large tasks should be split into smaller subtasks,
* usually via recursive decomposition. As a very rough rule of thumb,
* a task should perform more than 100 and less than 10000 basic
* computational steps, and should avoid indefinite looping. If tasks
* are too big, then parallelism cannot improve throughput. If too
* small, then memory and internal task maintenance overhead may
* overwhelm processing.
*
* <p>This class provides {@code adapt} methods for {@link Runnable}
* and {@link Callable}, that may be of use when mixing execution of
* {@code ForkJoinTasks} with other kinds of tasks. When all tasks are
* of this form, consider using a pool constructed in <em>asyncMode</em>.
*
* <p>ForkJoinTasks are {@code Serializable}, which enables them to be
* used in extensions such as remote execution frameworks. It is
* sensible to serialize tasks only before or after, but not during,
* execution. Serialization is not relied on during execution itself.
*
* @since 1.7
* @author Doug Lea
*/
/**
* 1、异常处理: 一般的ForkJoinTask需要依赖join()来传播异常,而CountedCompleter根据记录的
* completer 来传播异常。
*
* 2、awaitJoin(w, this)、 externalAwaitDone()总结
* awaitJoin(): 1、扫描自身的整个工作队列,判断任务是否存在,存在则取出执行;
* 2、如果任务是CountedCompleter 类型的任务,检查joiner工作队列的top位置,及其他工作线程(包括joiner)
* 的base位置的位置是否是目标任务task或者其子任务,若是取出并执行;
* 3、寻找并窃取task的一个子任务来执行,若子任务还进行分割,则执行完队列中的所有子任务;
* 4、若已经没有任务可以窃取,则为进入等待状态做准备,存在空闲线程则唤醒一个,如果没有空闲线程,且只剩下一个
* 活动的线程,则添加一个工作线程
* 5、修改任务状态表示有线程在等待任务完成,等任务完成后需要进行唤醒
*
* externalAwaitDone(): 1、如果当前任务是CountedCompleter 类型的任务,检查当前线程对应的队列中最后一个任务是否是目标任务或者其子任务,
* 是则取出执行,如果不是,继续轮询所有工作线程的队列的第一个任务是否目标任务或者其子任务,是则取出执行。如果
* 轮询两遍后没有任何进展,则返回,每当有进展,则重置轮询次数。
* 2、如果当前任务不是CountedCompleter 类型的任务,则检查当前线程对应的队列中的最后一个任务是否是目标任务,是则
* 取出执行。
*
*
*
*/
public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
/*
* 有关一般实现概述,请参阅ForkJoinPool类的内部文档。
* See the internal documentation of class ForkJoinPool for a
* general implementation overview. ForkJoinTasks are mainly
* 在ForkJoinWorkerThread和ForkJoinPool中,forkjointask主要负责在对
* 方法的中继中维护其“status”字段。
* responsible for maintaining their "status" field amidst relays
* to methods in ForkJoinWorkerThread and ForkJoinPool.
*
* 这个类的方法或多或少是分层的
* The methods of this class are more-or-less layered into
* (1) basic status maintenance 基本的状态维护
* (2) execution and awaiting completion 执行并等待完成
* (3) user-level methods that additionally report results. 额外报告结果的用户级方法。
* 有时很难看到这一点,因为这个文件以一种在javadocs中良好运行的方式对导出的方法进行排序。
* This is sometimes hard to see because this file orders exported
* methods in a way that flows well in javadocs.
*/
/*
* status字段将运行控制状态位打包到一个int中,以最小化内存占用并确保原子性(通过CAS)。
* The status field holds run control status bits packed into a
* single int to minimize footprint and to ensure atomicity (via
* CAS).
* Status最初为零,直到完成时才接受非负的值,在此状态下(用DONE_MASK进行处理)
* 保存值“NORMAL”、“cancel”或“exception”。
* Status is initially zero, and takes on nonnegative
* values until completed, upon which status (anded with
* DONE_MASK) holds value NORMAL, CANCELLED, or EXCEPTIONAL. Tasks
* 其他线程正在进行阻塞等待的任务将设置“SIGNAL”位。
* undergoing blocking waits by other threads have the SIGNAL bit
* 一个带有设置SIGNAL位的偷窃任务完成时会通过notifyAll唤醒所有的等待者
* set. Completion of a stolen task with SIGNAL set awakens any
* waiters via notifyAll.
* 尽管对于某些目的来说不是最优的,但是我们使用基本的内置wait/notify来利用jvm中的“监视膨胀”优点,
* 否则我们需要模拟它,以避免为每个任务增加更多的簿记开销。
* Even though suboptimal for some
* purposes, we use basic builtin wait/notify to take advantage of
* "monitor inflation" in JVMs that we would otherwise need to
* emulate to avoid adding further per-task bookkeeping overhead.
* 我们希望这些监视器是“胖”的,即不要使用偏置或细锁技术,因此要使用一些
* 奇怪的编码习惯来避免它们,主要是通过安排每个同步块执行一个wait,notifyAll或两者。
* We want these monitors to be "fat", i.e., not use biasing or
* thin-lock techniques, so use some odd coding idioms that tend
* to avoid them, mainly by arranging that every synchronized
* block performs a wait, notifyAll or both.
*
* 这些控制位只占用status字段的上半部分(16位
5 ForkJoinTask 源码注释
最新推荐文章于 2024-08-06 01:46:04 发布
本文详细分析了Java中ForkJoinTask的工作原理和实现细节,通过源码注释帮助读者深入理解其并发处理机制,包括任务的创建、分割、执行和结果合并等关键步骤。
摘要由CSDN通过智能技术生成