Java8 ForkJoinTask 源码解析

目录

1、定义

2、fork 

3、join / quietlyJoin

4、invoke / quietlyInvoke

5、complete / quietlyComplete/ completeExceptionally

6、recordExceptionalCompletion / clearExceptionalCompletion / getException 

7、invokeAll

8、get

9、tryUnfork / reinitialize


      本篇博客讲解ForkJoinTask的fork,join,invoke等方法的实现细节及其使用。

1、定义

       ForkJoinTask表示在ForkJoinPool中执行的一个任务,其类继承关系如下:

该类是一个抽象类,有多个子类,如下:

带S的几个大都是ForkJoinTask的内部类,其实现比较简单,用于将Runnable等接口转换成ForkJoinTask类,对应于ForkJoinPool的adapt方法,以AdaptedCallable的实现为例说明,如下:

public static <T> ForkJoinTask<T> adapt(Callable<? extends T> callable) {
        return new AdaptedCallable<T>(callable);
    }

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; }

        //改写核心的exec方法
        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;
    }

该类包含的属性如下:

 //保存ExceptionNode的数组,单个数组元素对应一个ExceptionNode链表
 private static final ExceptionNode[] exceptionTable;

 //修改exceptionTable时的锁
 private static final ReentrantLock exceptionTableLock;
 
 //保存被清楚掉的弱引用的队列   
 private static final ReferenceQueue<Object> exceptionTableRefQueue;

 //任务的状态,初始值为0,大于等于0时表示任务未执行或者正在执行的过程中,小于0表示已执行完成
 volatile int status; // accessed directly by pool and workers

  静态属性通过static代码块初始化,如下:

  该类定义的常量如下:

    //最高位为1
    static final int DONE_MASK   = 0xf0000000;  // mask out non-completion bits
    
    //正常完成
    static final int NORMAL      = 0xf0000000;  // must be negative
    
    //任务被取消了
    static final int CANCELLED   = 0xc0000000;  // must be < NORMAL
    
    //任务异常终止
    static final int EXCEPTIONAL = 0x80000000;  // must be < CANCELLED
    
    //某个线程在等待当前任务执行完成,需要在任务结束时唤醒等待的线程
    static final int SIGNAL      = 0x00010000;  // must be >= 1 << 16
    
    //获取低16位的值
    static final int SMASK       = 0x0000ffff;  // short bits for tags

    private static final int EXCEPTION_MAP_CAPACITY = 32;

 其中ExceptionNode是一个继承自WeakReference的内部类,其定义如下:

 

多个ExceptionNode通过next属性构成一个链表。

2、fork 

      fork方法并不是如其方法名会fork一个新线程来执行任务,只是将任务提交到任务队列中而已,然后立即返回,不会等待任务执行完成,其实现如下:

//fork方法并不是如其命名会创建一个新线程来执行任务,只是将任务提交到任务队列中而已
public final ForkJoinTask<V> fork() {
        Thread t;
        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
            //如果当前线程是ForkJoinWorkerThread,将其提交到关联的WorkQueue中
            ((ForkJoinWorkerThread)t).workQueue.push(this);
        else
            //如果是普通线程,则提交到common线程池的任务队列中
            ForkJoinPool.common.externalPush(this);
        return this;
    }

其测试用例如下: 

 @Test
    public void test() throws Exception {
        ForkJoinTask task=ForkJoinTask.adapt(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread().getName()+" exit");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //提交任务到common线程池
        task.fork();
        //阻塞等待任务执行完成,get方法会将该任务从任务队列中pop出来并执行
        //所以run方法打印出来的线程名就是main
        task.get();
        System.out.println("main thread exit");
    }

其输出如下:

可以在adapt方法对应的AdaptedRunnableAction打断点,如下:

然后debug,观察调用链如下:

3、join / quietlyJoin

     join方法用于阻塞当前线程,等待任务执行完成,部分情形下会通过当前线程执行任务,如果异常结束或者被取消需要抛出异常;quietlyJoin方法只是阻塞当前线程等待任务执行完成,不会抛出异常;其实现如下:

//join方法等待任务执行完成并返回结果,如果出现异常则报告异常
public final V join() {
        int s;
        //doJoin方法会阻塞当前线程直到任务执行完成并返回任务的状态
        if ((s = doJoin() & DONE_MASK) != NORMAL)
            //如果不是正常完成的,则报告异常
            reportException(s);
        //返回执行结果,该方法是抽象方法    
        return getRawResult();
    }

public final void quietlyJoin() {
        doJoin(); //只是等待任务执行完成
    }


private void reportException(int s) {
        if (s == CANCELLED)
            //被取消了
            throw new CancellationException();
        if (s == EXCEPTIONAL)
            //重新抛出异常
            rethrow(getThrowableException());
    }

static void rethrow(Throwable ex) {
        if (ex != null)
            ForkJoinTask.<RuntimeException>uncheckedThrow(ex);
    }

@SuppressWarnings("unchecked") static <T extends Throwable>
        void uncheckedThrow(Throwable t) throws T {
        throw (T)t; // rely on vacuous cast
    }



private int doJoin() {
        int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;
        //status小于0说明任务已结束,直接返回
        return (s = status) < 0 ? s :
            //如果status大于等于0
            ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
            //如果当前线程是ForkJoinWorkerThread,执行tryUnpush,返回true以后执行doExec
            //如果tryUnpush返回false或者doExec返回大于等于0,则执行awaitJoin
            //如果this在任务队列的顶端,tryUnpush会将其pop出来,返回true,否则返回false
            (w = (wt = (ForkJoinWorkerThread)t).workQueue).
            tryUnpush(this) && (s = doExec()) < 0 ? s :
            //awaitJoin也是阻塞当前线程,直到任务执行完成
            wt.pool.awaitJoin(w, this, 0L) :
            //如果当前线程是普通的Java线程
            externalAwaitDone();
    }


//执行任务,doExec方法的返回值取决于exec方法,如果exec返回true,则doExec返回值小于0
//如果返回false,则doExec返回值大于等于0
final int doExec() {
        int s; boolean completed;
        if ((s = status) >= 0) {
            try {
                //exec是子类实现的方法
                completed = exec();
            } catch (Throwable rex) {
                //执行异常
                return setExceptionalCompletion(rex);
            }
            if (completed)
                //正常完成
                s = setCompletion(NORMAL);
        }
        return s;
    }

//阻塞普通Java线程等待任务执行完成
 private int externalAwaitDone() {
        int s = ((this instanceof CountedCompleter) ? // try helping
                 //如果是CountedCompleter,则通过externalHelpComplete方法阻塞当前线程等待任务完成
                 ForkJoinPool.common.externalHelpComplete(
                     (CountedCompleter<?>)this, 0) :
                 //如果是普通的ForkJoinTask,则通过tryExternalUnpush尝试将其从任务队列中pop出来,如果该任务位于任务队列顶端则pop成功并返回true
                 //pop成功后执行doExec方法,即通过当前线程完成任务
                 ForkJoinPool.common.tryExternalUnpush(this) ? doExec() : 0);
        if (s >= 0 && (s = status) >= 0) {
            boolean interrupted = false;
            do {
                //修改status,加上SIGNAL标识,表示有线程等待了
                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
                    synchronized (this) {
                        if (status >= 0) { //再次校验状态
                            try {
                                //0表示无期限等待,直到被唤醒
                                //任务执行完成,可通过setCompletion方法唤醒等待的线程
                                wait(0L);
                            } catch (InterruptedException ie) {
                                interrupted = true;
                            }
                        }
                        else
                            //任务已执行完成,则唤醒所有等待的线程
                            notifyAll();
                    }
                }
            } while ((s = status) >= 0);
            if (interrupted)
                //等待时被中断,将当前线程标记为已中断
                Thread.currentThread().interrupt();
        }
        return s;
    }

其测试用例如下:

 @Test
    public void test() throws Exception {
        ForkJoinTask task=ForkJoinTask.adapt(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread().getName()+" exit");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //提交任务到common线程池
        task.fork();
        //阻塞等待任务执行完成,join方法会将该任务从任务队列中pop出来并执行
        //所以run方法打印出来的线程名就是main
        task.join();
        System.out.println("main thread exit");
    }

4、invoke / quietlyInvoke

      invoke会立即执行当前任务,如果doExec方法返回值大于等于0说明还有其他的子任务未完成,则等待其他子任务执行完成,典型的应用场景就是CountedCompleter,RecursiveAction和RecursiveTask通常doExec返回值小于0,会在compute方法即执行exec方法时等待所有的子任务执行完成;quietlyInvoke和invoke 都是基于doInvoke实现,区别在于前者不关心执行的结果,不会抛出异常。其实现如下:

 public final V invoke() {
        int s;
        //通过doExec立即执行任务,如果任务未完成则等待
        if ((s = doInvoke() & DONE_MASK) != NORMAL)
            reportException(s); //任务被取消或者异常终止则抛出异常
        return getRawResult();
    }

 public final void quietlyInvoke() {
        doInvoke(); //不需要抛出异常
    }

private int doInvoke() {
        int s; Thread t; ForkJoinWorkerThread wt;
        //直接调用doExec方法执行任务,如果执行完成,则直接返回
        return (s = doExec()) < 0 ? s :
             //如果doExec的结果大于等于0,说明未完成,典型的如CountedCompleter的子类应用
            ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
            //如果是ForkJoinWorkerThread,通过awaitJoin方法等待任务执行完成
            (wt = (ForkJoinWorkerThread)t).pool.
            awaitJoin(wt.workQueue, this, 0L) :
            //普通的Java线程,通过externalAwaitDone等待任务执行完成
            externalAwaitDone();
    }

 测试用例如下:

@Test
    public void test3() throws Exception {
        Thread thread=Thread.currentThread();
        ForkJoinTask task=new ForkJoinTask() {
            @Override
            public Object getRawResult() {
                return null;
            }

            @Override
            protected void setRawResult(Object value) {

            }

            @Override
            protected boolean exec() {
                System.out.println(Thread.currentThread().getName()+" start run");
                if(thread==Thread.currentThread()){
                    return false;
                }else{
                    try {
                        Thread.sleep(2000);
                        System.out.println(Thread.currentThread().getName()+" exit");
                        return true;
                    } catch (InterruptedException e) {
                        return false;
                    }
                }
            }
        };
        ForkJoinPool.commonPool().submit(task);
        //阻塞当前线程,等待任务执行完成
        task.invoke();
        System.out.println("main thread exit");
    }

上述用例的运行结果有两种,如下图:

 第二种会无期限阻塞,第一种是正常退出,为啥会有这种情形了?main线程执行invoke方法,invoke方法调用doExec方法返回值等于0后就执行externalAwaitDone方法了,如果执行ForkJoinPool.common.tryExternalUnpush方法返回true,则再次执行doExec方法,因为返回值还是0,则通过wait方法等待了,因为没有其他线程唤醒该线程,就会无期限等待;如果执行ForkJoinPool.common.tryExternalUnpush方法返回false,说明某个Worker线程已经将该任务从任务队列中移走了,Worker线程会负责执行该任务并修改任务执行状态,如果Worker线程正在执行的过程中则wait等待Worker线程执行完成,Worker执行完成会唤醒等待的main线程,main线程判断任务已完成就正常退出了。

5、complete / quietlyComplete/ completeExceptionally

     这三个方法都是任务执行完成时调用的,其中complete方法用于保存任务执行的结果并修改状态,quietlyComplete方法只修改状态,completeExceptionally用于任务执行异常时保存异常信息并修改状态,其中只有quietlyComplete方法有调用方,都是CountedCompleter及其子类,其调用链如下:

这三个方法的实现如下: 

//保存任务执行的结果并修改任务状态
public void complete(V value) {
        try {
            //保存结果
            setRawResult(value);
        } catch (Throwable rex) {
            //出现异常,保存关联的异常
            setExceptionalCompletion(rex);
            return;
        }
        //修改状态,正常完成
        setCompletion(NORMAL);
    }

 
public final void quietlyComplete() {
        //修改状态正常完成
        setCompletion(NORMAL);
    }

//任务异常结束时,保存异常信息并修改状态
public void completeExceptionally(Throwable ex) {
        //记录异常信息并更新任务状态
        setExceptionalCompletion((ex instanceof RuntimeException) ||
                                 (ex instanceof Error) ? ex :
                                 new RuntimeException(ex)); //如果不是RuntimeException或者Error,则将其用RuntimeException包装一层
    }

 private int setCompletion(int completion) {
        for (int s;;) {
            if ((s = status) < 0) //如果已完成,直接返回
                return s;
            if (U.compareAndSwapInt(this, STATUS, s, s | completion)) {
                //cas修改状态成功
                if ((s >>> 16) != 0) //如果status中有SIGNAL标识,即有线程在等待当前任务执行完成
                    synchronized (this) { notifyAll(); } //唤醒等待的线程
                return completion;
            }
        }
    }

 private int setExceptionalCompletion(Throwable ex) {
        //记录异常信息并更新任务状态
        int s = recordExceptionalCompletion(ex);
        if ((s & DONE_MASK) == EXCEPTIONAL) //如果状态是异常完成,则执行钩子方法
            internalPropagateException(ex); //默认是空实现
        return s;
    }

  void internalPropagateException(Throwable ex) {
    }

6、recordExceptionalCompletion / clearExceptionalCompletion / getException 

     这几个方法都是异常处理的,recordExceptionalCompletion用于记录异常信息并修改任务状态,getException方法获取当前任务关联的异常信息,如果任务是正常结束的则返回null,如果是被取消则返回CancellationException,如果异常结束则返回执行任务过程中抛出的异常,clearExceptionalCompletion是reinitialize调用的,用于清理掉当前任务关联的异常信息。

//保存异常信息,并设置状态异常结束
final int recordExceptionalCompletion(Throwable ex) {
        int s;
        if ((s = status) >= 0) {
            //获取hash值
            int h = System.identityHashCode(this);
            final ReentrantLock lock = exceptionTableLock;
            lock.lock(); //加锁
            try {
                //清理掉已经被GC回收掉的ExceptionNode
                expungeStaleExceptions();
                ExceptionNode[] t = exceptionTable;
                //计算该节点的索引
                int i = h & (t.length - 1);
                for (ExceptionNode e = t[i]; ; e = e.next) {
                    if (e == null) {
                        //如果t[i]为null或者遍历完了没有找到匹配的,则创建一个新节点,插入到t[i]链表的前面
                        t[i] = new ExceptionNode(this, ex, t[i]);
                        break;
                    }
                    //找到目标节点
                    if (e.get() == this) // already present
                        break;
                }
            } finally {
                lock.unlock();
            }
            //设置状态,异常终止
            s = setCompletion(EXCEPTIONAL);
        }
        return s;
    }

public final Throwable getException() {
        int s = status & DONE_MASK; 
        return ((s >= NORMAL)    ? null : //如果是正常完成,则返回null
                (s == CANCELLED) ? new CancellationException() : //任务被取消,则返回CancellationException
                getThrowableException()); //任务异常结束,获取之前异常结束时保存的异常信息
    }

//将exceptionTableRefQueue中已经被GC回收掉的节点从exceptionTable中移除
private static void expungeStaleExceptions() {
         //poll方法移除并返回链表头,链表中的节点是已经被回收掉了
        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) //x就是链表第一个节点
                            t[i] = next;
                        else  //x是链表中某个节点
                            pred.next = next;
                        break;
                    }
                    //遍历下一个节点
                    pred = e;
                    e = next;
                }
            }
        }
    }

 private Throwable getThrowableException() {
        if ((status & DONE_MASK) != EXCEPTIONAL) //不是异常结束,返回null
            return null;
        int h = System.identityHashCode(this);
        ExceptionNode e;
        //加锁
        final ReentrantLock lock = exceptionTableLock;
        lock.lock();
        try {
            //清理掉已经被GC回收掉的ExceptionNode
            expungeStaleExceptions();
            ExceptionNode[] t = exceptionTable;
            //计算所属的数组元素
            e = t[h & (t.length - 1)];
            //遍历链表,e.get()方法返回该ExceptionNode关联的Task
            while (e != null && e.get() != this)
                e = e.next;
        } finally {
            lock.unlock();
        }
        Throwable ex;
        //没有找到当前Task 或者ex为null
        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,则创建一个新异常实例
                        Throwable wx = (Throwable)c.newInstance(ex);
                        return (wx == null) ? ex : wx;
                    }
                }
                if (noArgCtor != null) {
                    //有默认的无参构造函数,创建一个实例并设置ex
                    Throwable wx = (Throwable)(noArgCtor.newInstance());
                    if (wx != null) {
                        wx.initCause(ex);
                        return wx;
                    }
                }
            } catch (Exception ignore) {
            }
        }
        return ex;
    }

//清理掉当前Task关联的ExceptionNode
private void clearExceptionalCompletion() {
        //获取hash值
        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) //this是链表第一个节点
                        t[i] = next;
                    else
                        pred.next = next; //this是链表中的一个节点
                    break;
                }
                //遍历下一个节点
                pred = e;
                e = next;
            }
            //清理掉已经被GC回收掉的ExceptionNode
            expungeStaleExceptions();
            status = 0;
        } finally {
            lock.unlock();
        }
    }

7、invokeAll

     invokeAll方法有三个重载版本,都是等待多个任务执行完成,其中第一个任务都是有当前线程执行,其他任务是提交到线程池执行,多个任务时,如果有一个任务执行异常,则会取消掉剩余未执行的任务。其实现如下:

public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) {
        int s1, s2;
        t2.fork(); //将t2提交到任务队列
        if ((s1 = t1.doInvoke() & DONE_MASK) != NORMAL) //执行t1并等待其执行完成
            t1.reportException(s1); //不是正常结束则抛出异常
        if ((s2 = t2.doJoin() & DONE_MASK) != NORMAL) //等待t2执行完成
            t2.reportException(s2);
    }

//此时tasks相当于一个ForkJoinTask数组
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) {
                //某个ForkJoinTask为null
                if (ex == null)
                    ex = new NullPointerException();
            }
            else if (i != 0) //i不等于0的,将其提交到任务队列
                t.fork();
            //i等于0,立即执行并等待其执行完成    
            else if (t.doInvoke() < NORMAL && ex == null)
                ex = t.getException();
        }
        //从1开始往前遍历
        for (int i = 1; i <= last; ++i) {
            ForkJoinTask<?> t = tasks[i];
            if (t != null) {
                if (ex != null) //ex不为空,则取消任务
                    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<?>)) {
            //如果没有实现RandomAccess接口或者不是List类型
            invokeAll(tasks.toArray(new ForkJoinTask<?>[tasks.size()]));
            return tasks;
        }
        //是List类型且实现了RandomAccess接口
        @SuppressWarnings("unchecked")
        List<? extends ForkJoinTask<?>> ts =
            (List<? extends ForkJoinTask<?>>) tasks;
        Throwable ex = null;
        //逻辑同上
        int last = ts.size() - 1;
        //从last处往前遍历
        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();
        }
        //从1开始往后遍历
        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;
    }

8、get

      get方法是阻塞当前线程并等待任务执行完成,其效果和实现跟join方法基本一致,最大的区别在于如果线程等待的过程中被中断了,get方法会抛出异常InterruptedException,而join方法不会抛出异常,其实现如下:

 public final V get() throws InterruptedException, ExecutionException {
        //如果是ForkJoinWorkerThread执行doJoin 否则执行externalInterruptibleAwaitDone
        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,通过awaitJoin方法等待任务执行完成
                ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t;
                s = wt.pool.awaitJoin(wt.workQueue, this, deadline);
            }
            //如果是普通Java线程
            else if ((s = ((this instanceof CountedCompleter) ?
                           //如果是CountedCompleter,则通过externalHelpComplete等待其执行完成
                           ForkJoinPool.common.externalHelpComplete(
                               (CountedCompleter<?>)this, 0) :
                           //如果是普通的ForkJoinTask,尝试将其从任务队列中pop出来并执行    
                           ForkJoinPool.common.tryExternalUnpush(this) ?
                           doExec() : 0)) >= 0) {
                //如果tryExternalUnpush返回false或者doExec方法返回值大于等于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)) {
                        //cas修改状态加上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();
    }

//逻辑同externalAwaitDone,区别在于如果被中断抛出异常
//externalAwaitDone不会抛出异常,如果被中断了会将当前线程标记为已中断
private int externalInterruptibleAwaitDone() throws InterruptedException {
        int s;
        if (Thread.interrupted())
            throw new InterruptedException(); //被中断则抛出异常
        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;
    }

9、tryUnfork / reinitialize

//尝试将当前任务从任务队列中pop出来,然后可以在当前线程执行
public boolean tryUnfork() {
        Thread t;
        return (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
                ((ForkJoinWorkerThread)t).workQueue.tryUnpush(this) : //如果Worker线程,尝试将当前任务从其关联的WorkQueue中pop出来
                ForkJoinPool.common.tryExternalUnpush(this)); //非Worker线程,尝试将当前任务从probe属性关联的WorkQueue中pop出来
    }

//将任务恢复至初始状态,然后可正常执行
public void reinitialize() {
        if ((status & DONE_MASK) == EXCEPTIONAL)
            clearExceptionalCompletion(); //如果是异常结束,则清除关联的异常信息
        else
            //状态恢复成0
            status = 0;
    }

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java Spring Boot 是一款基于 Spring 框架的快速开发框架,可以帮助开发者快速搭建应用程序。Spring Boot 的核心设计理念是“约定优于配置”,它提供了一系列的默认配置,让开发者可以快速开发,同时也提供了一些自定义配置的方式。 Spring Boot 的源码解析主要包括以下几个方面: 1. 自动配置 Spring Boot 的自动配置是其最大的特点之一。通过自动配置,Spring Boot 可以根据 classpath 中的 jar 包,自动配置应用程序的各种组件,如数据库连接池、web 服务器等。自动配置的原理是基于 Spring 的 Condition 接口实现的,通过条件判断来决定是否需要进行自动配置。 2. 启动流程 Spring Boot 的启动流程是比较复杂的,其中最重要的是 SpringApplicationBuilder 类的 run() 方法。在 run() 方法中,Spring Boot 会根据应用程序的配置信息,创建一个 Spring 应用上下文,并启动 web 服务器。同时,Spring Boot 还会扫描应用程序中的各种组件,注册到 Spring 容器中。 3. 配置文件 Spring Boot 的配置文件支持多种格式,包括 properties、yml 等。在读取配置文件时,Spring Boot 会根据配置文件的后缀名,选择不同的解析器进行解析。在解析配置文件时,Spring Boot 还支持占位符和表达式,方便开发者进行配置。 4. 监控管理 Spring Boot 提供了一套完整的监控管理机制,包括应用程序的健康状况、性能指标、日志等。通过监控管理,开发者可以及时发现应用程序的问题,并进行调整和优化。 总之,Spring Boot 的源码解析是非常庞大和复杂的,需要深入理解 Spring 框架的原理和设计思想,才能更好地掌握 Spring Boot。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值