jdk-Futeure&ForkJoin framework source code learning

background

    Most of the daily computing tasks are performed serially, but if a complex task needs to be split into multiple small tasks, then in the past, it was realized by writing a recursive or cyclic computing algorithm by itself. Improvement, the ForkJoin framework was introduced in java7 to support this type of calculation, which can efficiently solve large tasks or some scenarios that require combined calculations.

Introduction to ForkJoin framework

02c68e7e05bdc2c2f260324150c0dc8c.png

Java's Fork-Join framework is a framework for multi-threaded parallel processing tasks, which is usually used to process CPU-intensive tasks. It is a class library provided in Java SE 7 and later, designed to help developers more easily write scalable parallel code.

The core idea of ​​the Fork-Join framework is the "divide and conquer algorithm", which splits a large task into several small subtasks, then recursively processes these subtasks, and finally combines their results to obtain a large the result of the task. Since each subtask can be executed independently, the advantages of multiple processors and multi-core CPUs can be used to process these subtasks in parallel, thereby improving the processing speed of the entire task.

When using the Fork-Join framework, you need to define a task inherited from RecursiveTask or RecursiveAction, and then use the ForkJoinPool.submit() method to submit the task to the Fork-Join thread pool for execution. Among them, RecursiveTask returns the result of the task, while RecursiveAction does not return the result.

The Fork-Join framework is not only convenient and simple to use, but also can automatically utilize multi-processors and multi-core CPUs to give full play to the advantages of hardware resources. At the same time, it also has many other details and performance optimization measures, such as work-stealing algorithms, etc., making it a powerful tool for processing parallel tasks.

Suggested reference: https://www.oracle.com/technical-resources/articles/java/fork-join.html

What is the difference between CPU-intensive and IO-intensive?

    CPU-intensive and IO-intensive refer to different types of computing tasks, and the difference is mainly in the utilization of system resources.

CPU-intensive tasks (CPU-bound) refer to tasks that require a large amount of CPU operations to complete, such as complex mathematical calculations, image processing, and scientific simulations. In this case, the performance of the hard disk and memory of the system is much better than that of the CPU. At this time, the CPU Loading is often 100%, and the I/O operation can be completed in a short time, so the CPU usage is very high, while the I/O The wait time is short, so the CPU does not need to wait for the I/O operation to complete.

IO-intensive tasks (I/O-bound) refer to tasks that require a large number of I/O operations to complete, such as file read and write, network transmission, database query, etc. In this case, the CPU performance of the system is much better than that of the hard disk and memory. At this time, the CPU is often waiting for the completion of I/O operations (such as hard disk read and write), and the CPU Loading is not high. In I/O-intensive tasks, most of the time will be spent waiting for the completion of I/O operations, while the CPU usage is relatively low. In practical applications, we need to choose the appropriate computer configuration and algorithm optimization strategy according to the different types of tasks. If it is a CPU-intensive task, you need to choose a powerful CPU and shorten the I/O waiting time as much as possible; and if it is an I/O-intensive task, you need to choose a high-speed hard disk and network device, and make it as reasonable as possible. Make better use of CPU resources.

Note: Since the python language is an interpreted language, it does not support CPU-intensive tasks very well, because only one thread of the python global interpreter (Global Interpreter Lock, GIL) can execute phton bytecode at a time, even if there are multiple threads, the same Moment of execution also cannot execute python bytecode at the same time. (It is serial), you can refer to: https://blog.csdn.net/qq_44993593/article/details/129120146

What is the difference between concurrency and parallelism?

    Parallel (Parallel): Parallel is to execute multiple tasks at the same time, and each task has its own processor or core to execute independently.

    Concurrent: Concurrency is the execution of multiple tasks within the same period of time. These tasks will alternately use CPU time slices for execution, making users feel that they are running at the same time.

Personal understanding: For example, during New Year’s greetings, relatives who come to your home in batches on the same day do not meet each other (concurrently), and all relatives come to your home together (parallel).

0d9a1b69c7548d5ceee39116d983e282.png

What is a work-stealing algorithm? What problem does it mainly solve?

    A work-stealing algorithm is a concurrent programming algorithm for task scheduling. This algorithm aims at the load balancing problem of task execution in a multi-threaded environment. Each thread executes tasks in its own queue. It saves the resources of the thread and prevents the thread from being idle due to waiting for some tasks.

Principle: The work-stealing algorithm is based on a double-ended queue (deque), each thread has its own work queue, and the execution order of tasks is first-in-first-out (FIFO). When a thread needs to execute a task, it will take out the last added task from its own queue for processing. If the queue of the thread is empty, it will go to the work queue of other threads to steal a task to execute. The stolen task is generally the beginning (head) task of other thread queues, which can effectively reduce the competition and conflict between threads. Lock competition, improve parallel processing speed.

advantage:

  • Ability to efficiently utilize CPU resources;

  • Fully exploit the performance of multi-core processors;

  • At the same time, it can also prevent threads from being idle due to waiting for some tasks;

  • shortcoming:

  • The more times the task is stolen, the harder it is to guarantee the load balance between threads;

  • In addition, in the case of low task parallelism, task stealing may add some additional overhead and reduce the performance of the program.

a2a0c01b4df9e7e58246f83ffb9cd43b.png

The implementation logic of the work-stealing algorithm is mainly divided into the following steps:

  1. Each thread has a work queue where tasks are executed in first-in-first-out (FIFO) order.

  2. When a thread needs to execute a task, it will take out the last added task from the end of its own queue for processing.

  3. If the thread's queue is empty, it will go to other threads' work queues to steal a task to execute. It should be noted here that the thread needs to select an appropriate stealing object to ensure the load balance of task stealing.

  4. Stealing tasks are generally performed from the beginning (queue head) of other thread queues. When a thread successfully steals a task from another thread's queue, it executes that task immediately.

  5. During task execution, threads may spawn new subtasks. These subtasks are placed in the thread's local work queue instead of being sent directly to other threads' queues to avoid lock contention.

  6. During the execution of tasks, threads will constantly check their own local queues and queues of other threads to ensure efficient execution and load balancing of tasks.

  7. When all tasks are completed, the thread exits.

Basic use of ForkJoin

Class Diagram

e11b3e63b4fca9224562e781a8fc77bb.png

Class description:

ForkJoinTask is a class in Java concurrent programming. It is a parallel processing framework based on the idea of ​​"divide and conquer" and combined with the "work stealing" algorithm.

In the java.util.concurrent package, ForkJoinTask is an abstract class that needs to be inherited to create concrete tasks. It can divide sub-tasks, use multithreading to execute these tasks in parallel, and merge the results together to finally get the result of the whole task.

Among them, commonly used subclasses include: =

RecursiveAction: for tasks that do not return results.

RecursiveTask: Used for tasks that return results.

When executing a task, ForkJoinPool will split the task into multiple small tasks, and each thread executes one of the small tasks. When the thread finishes executing its own task, it can "steal" the tasks in the queue of other threads to execute , so as to improve CPU usage and concurrency efficiency.

Compared with traditional multi-thread programming, using ForkJoinTask can make better use of CPU, reduce competition among threads, and improve program performance.

/**
 *
 * 功能描述: 
 *
 * @param: 通过fork/join 进行求合计算
 * @return: 
 * @auther: csh
 * @date: 2023/4/17 9:52 下午
 */
public class ArraySum extends RecursiveTask<Long> {
    
    private static final int THRESHOLD = 1000; // 阈值,当数组大小小于该值时不再进行拆分
    private long[] arr;
    private int start;
    private int end;
    
    public ArraySum(long[] arr, int start, int end) {
        this.arr = arr;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        if (end - start <= THRESHOLD) { // 如果数组大小小于阈值,直接计算
            long sum = 0L;
            for (int i = start; i < end; i++) {
                sum += arr[i];
            }
            return sum;
        } else { // 如果数组大小大于阈值,拆分为两个任务并执行
            int mid = (start + end) / 2;
            ArraySum left = new ArraySum(arr, start, mid);
            ArraySum right = new ArraySum(arr, mid, end);
            left.fork();
            right.fork();
            return left.join() + right.join();
        }
    }

    public static void main(String[] args) {
        int N = 100000;
        long[] arr = new long[N];
        for (int i = 0; i < N; i++) {
            arr[i] = i;
        }
        ForkJoinPool pool = new ForkJoinPool();
        long sum = pool.invoke(new ArraySum(arr, 0, arr.length));
        System.out.println("累加起来的结果是: " + sum);
    }
}

result

相加起来的结果是: 4999950000

Source code learning of fork/join

ForkJoinTask mainly uses the CAS operation of the Unsafe class to update the task status. When the task is completed, call the onCompletion(CountedCompleter caller) method to notify the task's dependent tasks or send a signal to the thread waiting for the task, so as to realize the merging and delivery of task results.

属性:
static final int REOPR_SIGNAL: 表示任务的初始状态,即等待被执行。
static final int DONE_MASK: 任务完成状态的标识。
static final int NORMAL: 任务正常完成。
static final int CANCELLED: 任务被取消。
static final int EXCEPTIONAL: 任务发生异常。
volatile int status: 表示任务的状态,取值可能为 REOPR_SIGNAL、NORMAL、CANCELLED 或 EXCEPTIONAL 中的一个。
volatile ForkJoinTask<?> next: 指向下一个等待执行的任务。
volatile Thread runner: 执行该任务的线程。
final short statusFlags: 表示任务的状态及其他一些控制信息。
final short mode: 表示任务的运行模式。
Throwable exception: 任务执行过程中发生异常时,保存该异常对象。
方法:
public final void fork(): 将该任务加入到当前工作线程队列中,等待被执行。
public final boolean isDone(): 判断该任务是否已完成。
public final boolean cancel(boolean mayInterruptIfRunning): 取消该任务的执行。
public final void completeExceptionally(Throwable ex): 异常完成该任务,并将发生的异常传递给等待该任务的线程。
protected abstract void compute(): 子类必须实现的计算方法,用于执行具体的任务逻辑。
public final void quietlyCompleteRoot(): 安静地完成该任务,并通知等待该任务的线程。如果该任务是根任务,则将结果放到 ForkJoinPool 中的队列中。
public final int getQueuedTaskCount(): 获取等待执行的任务个数。
public final boolean isCancelled(): 判断该任务是否已取消。
public final boolean isCompletedAbnormally(): 判断该任务是否发生异常。
public final boolean isCompletedNormally(): 判断该任务是否正常完成。
public final Throwable getException(): 获取该任务发生的异常。
public final ForkJoinTask<V> submit(): 将该任务提交到 ForkJoinPool 中执行,并返回该任务的结果。
public final V invoke(): 在当前线程中执行该任务,并返回该任务的结果。
public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2): 执行给定的两个任务,并等待这两个任务都完成。
public static <T> void invokeAll(ForkJoinTask<T>... tasks): 执行指定的一组任务,并等待所有任务都完成。
protected static void reportException(Throwable ex): 抛出给定的异常。
私有方法:
final int setCompletion(int completion): 原子性地将该任务的状态修改为完成状态,同时返回原状态值。
final int doExec(): 执行当前任务的 compute() 方法,并返回任务的状态值。
final boolean trySetSignal(): 尝试将当前任务的状态从新建转换为信号状态 REOPR_SIGNAL。
static void internalPropagateException(Throwable ex): 尝试将给定的异常对象抛出到外层任务。
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;
//为抽象类必须被实现,实现Future
public abstract class ForkJoinTask<V> implements Future<V>, Serializable {


    /** 状态:初始状态:status = SIGNAL
           正常完成状态:status = NORMAL
           取消状态:status = CANCELLED
           异常状态:status = EXCEPTIONAL */
    volatile int status; // accessed directly by pool and workers
    static final int DONE_MASK = 0xf0000000; // 任务完成时的标识。
    static final int NORMAL = 0xf0000000; // 正常任务状态。
    static final int CANCELLED = 0xc0000000; // 取消状态。
    static final int EXCEPTIONAL = 0x80000000; // 异常状态。
    static final int SIGNAL = 0x00010000; // 初始状态 必须为 >= 1 << 16
    static final int SMASK = 0x0000ffff; // 低位掩码,也是最大索引位

    /**
     * 原子性地将该任务的状态修改为完成状态,同时返回原状态值。
     入参为状态
     */
    private int setCompletion(int completion) {
        for (int s;;) {
            if ((s = status) < 0)
                return s;
            if (U.compareAndSwapInt(this, STATUS, s, s | completion)) {
                if ((s >>> 16) != 0)
                    synchronized (this) { notifyAll(); }
                return completion;
            }
        }
    }

    /**
     *执行当前任务的 compute() 方法,并返回任务的状态值。
     */
    final int doExec() {
        int s; boolean completed;
        //状态大于0
        if ((s = status) >= 0) {
            try {
                //立即执行任务
                completed = exec();
            } catch (Throwable rex) {
                return setExceptionalCompletion(rex);
            }
            //执行后状态判断
            if (completed)
                //设置状态为正常任务状态。
                s = setCompletion(NORMAL);
        }
        //返回状态
        return s;
    }

    /**
     * 在等待该任务完成时,使用指定的超时时间来阻塞当前线程。
     */
    final void internalWait(long timeout) {
        int s;
        //正常状态才继续
        if ((s = status) >= 0 && // force completer to issue notify
            //又是Unsafe 的cas来更改状态
            U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
            //同步块
            synchronized (this) {
                //状态大于0 正常 等待timeout时间
                if (status >= 0)
                    try { wait(timeout); } catch (InterruptedException ie) { }
                else
                    //唤醒所有任务
                    notifyAll();
            }
        }
    }

    /**
     * 阻止非工作线程,直到完成。
     */
    private int externalAwaitDone() {
        //判断类型获取池中的状态
        int s = ((this instanceof CountedCompleter) ? // try helping
                 ForkJoinPool.common.externalHelpComplete(
                     (CountedCompleter<?>)this, 0) :
                 ForkJoinPool.common.tryExternalUnpush(this) ? doExec() : 0);
        //大于0证明不是初始化及已结束
        if (s >= 0 && (s = status) >= 0) {
            boolean interrupted = false;
            do {
                //通过循环方式进行cas设置锁
                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
                    synchronized (this) {
                        if (status >= 0) {
                            try {
                                wait(0L);
                            } catch (InterruptedException ie) {
                                interrupted = true;
                            }
                        }
                        else
                            notifyAll();
                    }
                }
            } while ((s = status) >= 0);
            //中断状态为true(有可能结束或异常了)
            if (interrupted)
                //进行当前线程中断
                Thread.currentThread().interrupt();
        }
        //反回状态
        return s;
    }

    /**
     * 等待该任务完成,并允许在等待的过程中中断当前线程。
     该方法通过调用 LockSupport.park(this) 方法来实现线程等待,如果当前线程被中断,则会抛出 InterruptedException 异常。
     */
    private int externalInterruptibleAwaitDone() throws InterruptedException {
        int s;
        //中断线程成功 直接抛出
        if (Thread.interrupted())
            throw new InterruptedException();
        //如果状态大于0 且 尝试通过线程池进行执行所有任务 证明正常
        if ((s = status) >= 0 &&
            (s = ((this instanceof CountedCompleter) ?
                  ForkJoinPool.common.externalHelpComplete(
                      (CountedCompleter<?>)this, 0) :
                  ForkJoinPool.common.tryExternalUnpush(this) ? doExec() :
                  0)) >= 0) {
            //循环进行状态置为初始化
            while ((s = status) >= 0) {
                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
                    synchronized (this) {
                        if (status >= 0)
                            wait(0L);
                        else
                            notifyAll();
                    }
                }
            }
        }
        return s;
    }

    /**
     * 等待该任务完成,并返回任务的状态。
     在等待任务完成的过程中,使用自旋锁的方式不断地检查任务状态。
     如果任务状态为完成状态,则返回该任务的状态;否则,使用 LockSupport.park(this) 方法挂起当前线程,并等待任务完成。
     注意:这个方法在等待过程中由于使用了自旋锁和线程挂起的方式,因此可能会消耗大量的 CPU 资源。
     *
     */
    private int doJoin() {
        //参数声名 状态:s 线程:t 工作线程:wt 工作队列:w
        int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;
        //获取状态如果小于0 当前线程中断 否则进行结束
        return (s = status) < 0 ? s :
            ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
            (w = (wt = (ForkJoinWorkerThread)t).workQueue).
            tryUnpush(this) && (s = doExec()) < 0 ? s :
            wt.pool.awaitJoin(w, this, 0L) :
            externalAwaitDone();
    }

    /**
     * 在当前线程中执行该任务,并返回任务的状态值(同上类似)
     */
    private int doInvoke() {
        int s; Thread t; ForkJoinWorkerThread wt;
        return (s = doExec()) < 0 ? s :
            ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
            (wt = (ForkJoinWorkerThread)t).pool.
            awaitJoin(wt.workQueue, this, 0L) :
            externalAwaitDone();
    }

    // Exception table support

    //任务异常列表
    private static final ExceptionNode[] exceptionTable;
    //任务异常重入锁
    private static final ReentrantLock exceptionTableLock;
    //存放异常的实例
    private static final ReferenceQueue<Object> exceptionTableRefQueue;

    /**
     * 异常表的固定容量。
     */
    private static final int EXCEPTION_MAP_CAPACITY = 32;

    //异常节点类实现
    static final class ExceptionNode extends WeakReference<ForkJoinTask<?>> {
        final Throwable ex;
        ExceptionNode next;
        final long thrower; // use id not ref to avoid weak cycles
        final int hashCode; // store task hashCode before weak ref disappears
        ExceptionNode(ForkJoinTask<?> task, Throwable ex, ExceptionNode next) {
            super(task, exceptionTableRefQueue);
            this.ex = ex;
            this.next = next;
            this.thrower = Thread.currentThread().getId();
            this.hashCode = System.identityHashCode(task);
        }
    }

    /**
     * 记录异常并设置状态。
     *
     * @return status on exit
     */
    final int recordExceptionalCompletion(Throwable ex) {
        int s;
        //状态大于等于0
        if ((s = status) >= 0) {
            int h = System.identityHashCode(this);
            //上锁
            final ReentrantLock lock = exceptionTableLock;
            lock.lock();
            try {
                expungeStaleExceptions();
                ExceptionNode[] t = exceptionTable;
                int i = h & (t.length - 1);
                //循环创建
                for (ExceptionNode e = t[i]; ; e = e.next) {
                    if (e == null) {
                        t[i] = new ExceptionNode(this, ex, t[i]);
                        break;
                    }
                    if (e.get() == this) // already present
                        break;
                }
            } finally {
                lock.unlock();
            }
            s = setCompletion(EXCEPTIONAL);
        }
        return s;
    }

    /**
     * 记录异常并可能传播。
     *
     * @return status on exit
     */
    private int setExceptionalCompletion(Throwable ex) {
        int s = recordExceptionalCompletion(ex);
        if ((s & DONE_MASK) == EXCEPTIONAL)
            internalPropagateException(ex);
        return s;
    }

    /**
     * Hook for exception propagation support for tasks with completers.
     */
    void internalPropagateException(Throwable ex) {
    }

    /**
     * 取消,忽略取消引发的任何异常。
     */
    static final void cancelIgnoringExceptions(ForkJoinTask<?> t) {
        if (t != null && t.status >= 0) {
            try {
                //取消
                t.cancel(false);
            } catch (Throwable ignore) {
            }
        }
    }

    /**
     * 删除异常节点并清除状态。
     */
    private void clearExceptionalCompletion() {
        int h = System.identityHashCode(this);
        final ReentrantLock lock = exceptionTableLock;
        //上锁
        lock.lock();
        try {
            ExceptionNode[] t = exceptionTable;
            int i = h & (t.length - 1);
            ExceptionNode e = t[i];
            ExceptionNode pred = null;
            //循环处理
            while (e != null) {
                ExceptionNode next = e.next;
                if (e.get() == this) {
                    if (pred == null)
                        t[i] = next;
                    else
                        pred.next = next;
                    break;
                }
                pred = e;
                e = next;
            }
            expungeStaleExceptions();
            status = 0;
        } finally {
            //释放锁
            lock.unlock();
        }
    }

    //获取异常
    private Throwable getThrowableException() {
        //不是异常直接返回空
        if ((status & DONE_MASK) != EXCEPTIONAL)
            return null;
        //获取哈希code
        int h = System.identityHashCode(this);
        ExceptionNode e;
        //上锁
        final ReentrantLock lock = exceptionTableLock;
        lock.lock();
        try {
            //删除过期的引用
            expungeStaleExceptions();
            ExceptionNode[] t = exceptionTable;
            e = t[h & (t.length - 1)];
            while (e != null && e.get() != this)
                e = e.next;
        } finally {
            lock.unlock();
        }
        Throwable ex;
        if (e == null || (ex = e.ex) == null)
            return null;
        if (e.thrower != Thread.currentThread().getId()) {
            Class<? extends Throwable> ec = ex.getClass();
            try {
                Constructor<?> noArgCtor = null;
                Constructor<?>[] cs = ec.getConstructors();// public ctors only
                for (int i = 0; i < cs.length; ++i) {
                    Constructor<?> c = cs[i];
                    Class<?>[] ps = c.getParameterTypes();
                    if (ps.length == 0)
                        noArgCtor = c;
                    else if (ps.length == 1 && ps[0] == Throwable.class) {
                        Throwable wx = (Throwable)c.newInstance(ex);
                        return (wx == null) ? ex : wx;
                    }
                }
                if (noArgCtor != null) {
                    Throwable wx = (Throwable)(noArgCtor.newInstance());
                    if (wx != null) {
                        wx.initCause(ex);
                        return wx;
                    }
                }
            } catch (Exception ignore) {
            }
        }
        return ex;
    }

    /**
     * 删除过期引用的实现方法
     */
    private static void expungeStaleExceptions() {
        //循环筛选
        for (Object x; (x = exceptionTableRefQueue.poll()) != null;) {
            if (x instanceof ExceptionNode) {
                int hashCode = ((ExceptionNode)x).hashCode;
                ExceptionNode[] t = exceptionTable;
                int i = hashCode & (t.length - 1);
                ExceptionNode e = t[i];
                ExceptionNode pred = null;
                while (e != null) {
                    ExceptionNode next = e.next;
                    if (e == x) {
                        if (pred == null)
                            t[i] = next;
                        else
                            pred.next = next;
                        break;
                    }
                    pred = e;
                    e = next;
                }
            }
        }
    }

    /**
     * 轮询过时的引用并将其删除(带锁)
     */
    static final void helpExpungeStaleExceptions() {
        final ReentrantLock lock = exceptionTableLock;
        if (lock.tryLock()) {
            try {
                //调用上面的方法
                expungeStaleExceptions();
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * 重新抛出异常的方法
     */
    static void rethrow(Throwable ex) {
        if (ex != null)
            ForkJoinTask.<RuntimeException>uncheckedThrow(ex);
    }

    /**
     * The sneaky part of sneaky throw, relying on generics
     * limitations to evade compiler complaints about rethrowing
     * unchecked exceptions
     */
    @SuppressWarnings("unchecked") static <T extends Throwable>
        void uncheckedThrow(Throwable t) throws T {
        throw (T)t; // rely on vacuous cast
    }

    /**
     * 根据s的不同抛出不同的异常
     */
    private void reportException(int s) {
        if (s == CANCELLED)
            throw new CancellationException();
        if (s == EXCEPTIONAL)
            rethrow(getThrowableException());
    }

    // public methods

    /**
     * 将该任务加入到当前工作线程队列中,等待被执行。
     */
    public final ForkJoinTask<V> fork() {
        Thread t;
        //获取当前线程 判断是否为ForkJoinWorkerThread类型,是的话加入工作队列
        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
            ((ForkJoinWorkerThread)t).workQueue.push(this);
        else
            //不是则加入工作池队列
            ForkJoinPool.common.externalPush(this);
        return this;
    }

    /**
     *返回计算的结果
     注意:此方法异常会导致中断
     */
    public final V join() {
        int s;
        if ((s = doJoin() & DONE_MASK) != NORMAL)
            reportException(s);
        //返回计算结果
        return getRawResult();
    }

    /**
     * 在当前线程中执行该任务,并返回该任务的结果。
     *
     * 返回计算结果
     */
    public final V invoke() {
        int s;
        if ((s = doInvoke() & DONE_MASK) != NORMAL)
            reportException(s);
        return getRawResult();
    }

    /**
     * 执行给定的两个任务,并等待这两个任务都完成。
     */
    public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) {
        int s1, s2;
        t2.fork();
        if ((s1 = t1.doInvoke() & DONE_MASK) != NORMAL)
            t1.reportException(s1);
        if ((s2 = t2.doJoin() & DONE_MASK) != NORMAL)
            t2.reportException(s2);
    }

    /**
     * 执行指定的一组任务,并等待所有任务都完成。
     */
    public static void invokeAll(ForkJoinTask<?>... tasks) {
        Throwable ex = null;
        //获取最后一个节点下标
        int last = tasks.length - 1;
        //倒序
        for (int i = last; i >= 0; --i) {
            //获取对象
            ForkJoinTask<?> t = tasks[i];
            //为空 进行抛出空指针异常
            if (t == null) {
                if (ex == null)
                    ex = new NullPointerException();
            }
            //不为空 进行加入队列
            else if (i != 0)
                t.fork();
            //执行并返回结果 如果状态为NORMAL 且 ex为空抛出异常
            else if (t.doInvoke() < NORMAL && ex == null)
                ex = t.getException();
        }
        //自增进行
        for (int i = 1; i <= last; ++i) {
            ForkJoinTask<?> t = tasks[i];
            if (t != null) {
                if (ex != null)
                    t.cancel(false);
                //加入执行队列
                else if (t.doJoin() < NORMAL)
                    ex = t.getException();
            }
        }
        //异常不为空则抛出异常
        if (ex != null)
            rethrow(ex);
    }

    //同上类似
    public static <T extends ForkJoinTask<?>> Collection<T> invokeAll(Collection<T> tasks) {
        if (!(tasks instanceof RandomAccess) || !(tasks instanceof List<?>)) {
            invokeAll(tasks.toArray(new ForkJoinTask<?>[tasks.size()]));
            return tasks;
        }
        @SuppressWarnings("unchecked")
        List<? extends ForkJoinTask<?>> ts =
            (List<? extends ForkJoinTask<?>>) tasks;
        Throwable ex = null;
        int last = ts.size() - 1;
        for (int i = last; i >= 0; --i) {
            ForkJoinTask<?> t = ts.get(i);
            if (t == null) {
                if (ex == null)
                    ex = new NullPointerException();
            }
            else if (i != 0)
                t.fork();
            else if (t.doInvoke() < NORMAL && ex == null)
                ex = t.getException();
        }
        for (int i = 1; i <= last; ++i) {
            ForkJoinTask<?> t = ts.get(i);
            if (t != null) {
                if (ex != null)
                    t.cancel(false);
                else if (t.doJoin() < NORMAL)
                    ex = t.getException();
            }
        }
        if (ex != null)
            rethrow(ex);
        return tasks;
    }

    //尝试取消此任务的执行。
    public boolean cancel(boolean mayInterruptIfRunning) {
        return (setCompletion(CANCELLED) & DONE_MASK) == CANCELLED;
    }
    //判断是否结束 true是 false否
    public final boolean isDone() {
        return status < 0;
    }
    // 判断该任务是否已取消。
    public final boolean isCancelled() {
        return (status & DONE_MASK) == CANCELLED;
    }

    /**
     * 判断该任务是否发生异常。true是 false否
     */
    public final boolean isCompletedAbnormally() {
        return status < NORMAL;
    }

    /**
     * 判断该任务是否正常完成。true是 false否
     */
    public final boolean isCompletedNormally() {
        return (status & DONE_MASK) == NORMAL;
    }

    /**
     * 获取异常
    public final Throwable getException() {
        int s = status & DONE_MASK;
        return ((s >= NORMAL) ? null :
                (s == CANCELLED) ? new CancellationException() :
                getThrowableException());
    }

    /**
     * 异常完成该任务,并将发生的异常传递给等待该任务的线程。
     */
    public void completeExceptionally(Throwable ex) {
        setExceptionalCompletion((ex instanceof RuntimeException) ||
                                 (ex instanceof Error) ? ex :
                                 new RuntimeException(ex));
    }

    /**
     *用于执行具体的任务逻辑。
     */
    public void complete(V value) {
        try {
            setRawResult(value);
        } catch (Throwable rex) {
            setExceptionalCompletion(rex);
            return;
        }
        setCompletion(NORMAL);
    }

    /**
     * 在不设置值的情况下正常完成此任务
     *
     * @since 1.8
     */
    public final void quietlyComplete() {
        setCompletion(NORMAL);
    }

    /**等待计算完成,然后检索其结果。
     */
    public final V get() throws InterruptedException, ExecutionException {
        int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ?
            doJoin() : externalInterruptibleAwaitDone();
        Throwable ex;
        if ((s &= DONE_MASK) == CANCELLED)
            throw new CancellationException();
        if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
            throw new ExecutionException(ex);
        return getRawResult();
    }

    /**
     * 带超时的等待执行结束,获取结果
     */
    public final V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        int s;
        long nanos = unit.toNanos(timeout);
        if (Thread.interrupted())
            throw new InterruptedException();
        if ((s = status) >= 0 && nanos > 0L) {
            long d = System.nanoTime() + nanos;
            long deadline = (d == 0L) ? 1L : d; // avoid 0
            Thread t = Thread.currentThread();
            if (t instanceof ForkJoinWorkerThread) {
                ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t;
                s = wt.pool.awaitJoin(wt.workQueue, this, deadline);
            }
            else if ((s = ((this instanceof CountedCompleter) ?
                           ForkJoinPool.common.externalHelpComplete(
                               (CountedCompleter<?>)this, 0) :
                           ForkJoinPool.common.tryExternalUnpush(this) ?
                           doExec() : 0)) >= 0) {
                long ns, ms; // measure in nanosecs, but wait in millisecs
                while ((s = status) >= 0 &&
                       (ns = deadline - System.nanoTime()) > 0L) {
                    if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L &&
                        U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
                        synchronized (this) {
                            if (status >= 0)
                                wait(ms); // OK to throw InterruptedException
                            else
                                notifyAll();
                        }
                    }
                }
            }
        }
        if (s >= 0)
            s = status;
        if ((s &= DONE_MASK) != NORMAL) {
            Throwable ex;
            if (s == CANCELLED)
                throw new CancellationException();
            if (s != EXCEPTIONAL)
                throw new TimeoutException();
            if ((ex = getThrowableException()) != null)
                throw new ExecutionException(ex);
        }
        return getRawResult();
    }

    /**
     * 加入此任务,而不返回其结果或引发其异常。
     */
    public final void quietlyJoin() {
        doJoin();
    }

    /**
     *开始执行此任务,并在必要时等待其完成,而不返回其结果或引发其异常。
     */
    public final void quietlyInvoke() {
        doInvoke();
    }

    /**
     * 用于等待所有正在执行的任务完成。
     */
    public static void helpQuiesce() {
        Thread t;
        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
            ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t;
            wt.pool.helpQuiescePool(wt.workQueue);
        }
        else
            ForkJoinPool.quiesceCommonPool();
    }

    /**
     * 重置此任务的内部簿记状态,允许后续
     */
    public void reinitialize() {
        if ((status & DONE_MASK) == EXCEPTIONAL)
            clearExceptionalCompletion();
        else
            status = 0;
    }

    /**
     * 获取任务线程池
     */
    public static ForkJoinPool getPool() {
        Thread t = Thread.currentThread();
        return (t instanceof ForkJoinWorkerThread) ?
            ((ForkJoinWorkerThread) t).pool : null;
    }

    /**
     *判断当前是否为线程池执行,如果是则返回true
     */
    public static boolean inForkJoinPool() {
        return Thread.currentThread() instanceof ForkJoinWorkerThread;
    }

    /**
     * 尝试取消执行的任务
     */
    public boolean tryUnfork() {
        Thread t;
        //获取当前线程 判断在池中还是队列,然后进行取消
        return (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
                ((ForkJoinWorkerThread)t).workQueue.tryUnpush(this) :
                ForkJoinPool.common.tryExternalUnpush(this));
    }

    /**
     * 返回当前任务的队列计数(排队数)
     */
    public static int getQueuedTaskCount() {
        Thread t; ForkJoinPool.WorkQueue q;
        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
            q = ((ForkJoinWorkerThread)t).workQueue;
        else
            q = ForkJoinPool.commonSubmitterQueue();
        return (q == null) ? 0 : q.queueSize();
    }

    /**
     * 获取线程池中的排队数
     *
     * @return the surplus number of tasks, which may be negative
     */
    public static int getSurplusQueuedTaskCount() {
        return ForkJoinPool.getSurplusQueuedTaskCount();
    }

    // Extension methods

    /**
     * 返回的结果(即使此任务异常完成)或 {@code null}(如果此任务未知已完成)
     *
     * @return the result, or {@code null} if not completed
     */
    public abstract V getRawResult();

    /**
     * Forces the given value to be returned as a result. This method
     * is designed to support extensions, and should not in general be
     * called otherwise.
     *
     * @param value the value
     */
    protected abstract void setRawResult(V value);

    /**
     * 抽象的执行方法 (子类需要实现)
     */
    protected abstract boolean exec();

    /**
     * 获取当前排队中的任务
     */
    protected static ForkJoinTask<?> peekNextLocalTask() {
        Thread t; ForkJoinPool.WorkQueue q;
        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
            q = ((ForkJoinWorkerThread)t).workQueue;
        else
            q = ForkJoinPool.commonSubmitterQueue();
        return (q == null) ? null : q.peek();
    }

    /**
     * 用于从当前线程绑定的工作队列中获取下一个待执行的任务。
     */
    protected static ForkJoinTask<?> pollNextLocalTask() {
        Thread t;
        return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
            ((ForkJoinWorkerThread)t).workQueue.nextLocalTask() :
            null;
    }

    /**
     * 用于从当前线程绑定的工作队列和共享队列中获取下一个待执行的任务。
     */
    protected static ForkJoinTask<?> pollTask() {
        Thread t; ForkJoinWorkerThread wt;
        return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
            (wt = (ForkJoinWorkerThread)t).pool.nextTaskFor(wt.workQueue) :
            null;
    }

    // tag operations

    /**
     * 获取当前状态
     * @since 1.8
     */
    public final short getForkJoinTaskTag() {
        return (short)status;
    }

    /**
     * 以原子方式设置此任务的标记值。
     */
    public final short setForkJoinTaskTag(short tag) {
        for (int s;;) {
            if (U.compareAndSwapInt(this, STATUS, s = status,
                                    (s & ~SMASK) | (tag & SMASK)))
                return (short)s;
        }
    }

    /**
     *以原子方式有条件地设置此任务的标记值。
     */
    public final boolean compareAndSetForkJoinTaskTag(short e, short tag) {
        for (int s;;) {
            if ((short)(s = status) != e)
                return false;
            if (U.compareAndSwapInt(this, STATUS, s,
                                    (s & ~SMASK) | (tag & SMASK)))
                return true;
        }
    }

    /**
     * 适配器类
     */
    static final class AdaptedRunnable<T> extends ForkJoinTask<T>
        implements RunnableFuture<T> {
        //用于存储被适配的 Runnable 对象。
        final Runnable runnable;
        T result;
        //构造方法 线程和结果为入参
        AdaptedRunnable(Runnable runnable, T result) {
            if (runnable == null) throw new NullPointerException();
            this.runnable = runnable;
            this.result = result; // OK to set this even before completion
        }
        //获取执行结果方法
        public final T getRawResult() { return result; }
        //设置执行结果方法
        public final void setRawResult(T v) { result = v; }
        //执行返回true
        public final boolean exec() { runnable.run(); return true; }
        //运行无返回
        public final void run() { invoke(); }
        private static final long serialVersionUID = 5232453952276885070L;
    }

    /**
     * 有返回的适配器类 与上面的类似,唯一的区别是没有返回
     */
    static final class AdaptedRunnableAction extends ForkJoinTask<Void>
        implements RunnableFuture<Void> {
        final Runnable runnable;
        AdaptedRunnableAction(Runnable runnable) {
            if (runnable == null) throw new NullPointerException();
            this.runnable = runnable;
        }
        public final Void getRawResult() { return null; }
        public final void setRawResult(Void v) { }
        public final boolean exec() { runnable.run(); return true; }
        public final void run() { invoke(); }
        private static final long serialVersionUID = 5232453952276885070L;
    }

    /**
     * 同上类似(带异常)
     */
    static final class RunnableExecuteAction extends ForkJoinTask<Void> {
        final Runnable runnable;
        RunnableExecuteAction(Runnable runnable) {
            if (runnable == null) throw new NullPointerException();
            this.runnable = runnable;
        }
        public final Void getRawResult() { return null; }
        public final void setRawResult(Void v) { }
        public final boolean exec() { runnable.run(); return true; }
        void internalPropagateException(Throwable ex) {
            rethrow(ex); // rethrow outside exec() catches.
        }
        private static final long serialVersionUID = 5232453952276885070L;
    }

    /**
     * 适配器
     */
    static final class AdaptedCallable<T> extends ForkJoinTask<T>
        implements RunnableFuture<T> {
        final Callable<? extends T> callable;
        T result;
        AdaptedCallable(Callable<? extends T> callable) {
            if (callable == null) throw new NullPointerException();
            this.callable = callable;
        }
        public final T getRawResult() { return result; }
        public final void setRawResult(T v) { result = v; }
        public final boolean exec() {
            try {
                result = callable.call();
                return true;
            } catch (Error err) {
                throw err;
            } catch (RuntimeException rex) {
                throw rex;
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }
        public final void run() { invoke(); }
        private static final long serialVersionUID = 2838392045355241008L;
    }

    /**
     * 返回一个新的AdaptedRunnableAction适配器
     */
    public static ForkJoinTask<?> adapt(Runnable runnable) {
        return new AdaptedRunnableAction(runnable);
    }

    /**
     * 返回一个AdaptedRunnable适配器
     */
    public static <T> ForkJoinTask<T> adapt(Runnable runnable, T result) {
        return new AdaptedRunnable<T>(runnable, result);
    }

    /**
     * 返回一个AdaptedCallable适配器
     */
    public static <T> ForkJoinTask<T> adapt(Callable<? extends T> callable) {
        return new AdaptedCallable<T>(callable);
    }

    // Serialization support

    private static final long serialVersionUID = -7721805057305804111L;

    /**
     * 输入对象流
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        s.defaultWriteObject();
        s.writeObject(getException());
    }

    /**
     * 读文件
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        Object ex = s.readObject();
        if (ex != null)
            setExceptionalCompletion((Throwable)ex);
    }

    // Unsafe mechanics
    private static final sun.misc.Unsafe U;
    private static final long STATUS;
    //初始化静态代码块
    static {
        //实例会异常锁
        exceptionTableLock = new ReentrantLock();
        //实例会引用对象
        exceptionTableRefQueue = new ReferenceQueue<Object>();
        //实例化异常节点对象
        exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY];
        try {
            //实例化unsafe
            U = sun.misc.Unsafe.getUnsafe();
            Class<?> k = ForkJoinTask.class;
            STATUS = U.objectFieldOffset
                (k.getDeclaredField("status"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }

}

at last

    It's a pity that so far, in many projects and with many colleagues or friends who are doing development, this ForkJoin is rarely used, and most of them still stay in CURD. It's a pity, but in fact, database query optimization, image processing, machine learning , Big data processing and other scenarios can be realized through the parallel processing capability of ForkJoin. Of course, there are many, many usages of this ForkJoin, you can understand it by yourself.

21332c054471b9caeec3152300bc10c1.png

Guess you like

Origin blog.csdn.net/qq_16498553/article/details/130256870