completableFuture.allOf().get()方法原理分析

文章详细解释了CompletableFuture的allOf()方法用于等待多个任务完成,get()方法内部通过waitingGet()实现线程等待。当result为null时,线程会进入阻塞状态,通过Signaller对象进行管理。在阻塞过程中,使用ForkJoinPool和ManagedBlocker接口配合LockSupport的park方法来控制线程的阻塞和唤醒,同时处理中断情况。
摘要由CSDN通过智能技术生成

completableFuture.allOf()用于多任务共同返回,配合get()使用来实现任务的等待。get()方法内部是waittingGet(),其是while()循环判断返回结果为null的话,则一直等待,如果线程不为null、返回结果为null,则线程阻塞等待。其源码如下:

 public T get() throws InterruptedException, ExecutionException {
        Object r;
        /* 
        分为两种,线程执行比较快或者慢。执行比较慢的就进入 waitingGet(true)方法进行阻塞。
        快的就直接返回结果信息
        */
        return reportGet((r = result) == null ? waitingGet(true) : r);
    }

 //这个返回主要判断这个result是什么类型进行相关处理
 private static <T> T reportGet(Object r)
        throws InterruptedException, ExecutionException {
        if (r == null) // by convention below, null means interrupted
            throw new InterruptedException();
        if (r instanceof AltResult) {
            Throwable x, cause;
            if ((x = ((AltResult)r).ex) == null)
                return null;
            if (x instanceof CancellationException)
                throw (CancellationException)x;
            if ((x instanceof CompletionException) &&
                (cause = x.getCause()) != null)
                x = cause;
            throw new ExecutionException(x);
        }
        @SuppressWarnings("unchecked") T t = (T) r;
        return t;
    }
    
 private Object waitingGet(boolean interruptible) {
        Signaller q = null;
        boolean queued = false;
        int spins = -1;
        Object r;
        while ((r = result) == null) {
            if (spins < 0)
                //获取当前处理数量是否大于1,大于1 spins = 256 否则 0
                spins = (Runtime.getRuntime().availableProcessors() > 1) ?
                    1 << 8 : 0; // Use brief spin-wait on multiprocessors
            else if (spins > 0) {
                //获取一个随机的数值,如果每次都大于等于0,--spins 到小于0为止
                if (ThreadLocalRandom.nextSecondarySeed() >= 0)
                    --spins;
            }
            else if (q == null)
               /**
                 注意,这个对象很关键。以下用q表示
		         Signaller(boolean interruptible, long nanos, long deadline) {
		            this.thread = Thread.currentThread();
		            this.interruptControl = interruptible ? 1 : 0;
		            this.nanos = nanos;
		            this.deadline = deadline;
		        }
               */
                q = new Signaller(interruptible, 0L, 0L);
            else if (!queued)
                /**
                		    stack		    next
          原       this      A			     B
                    q                        A           
          现       this      q               B  
                */
                queued = tryPushStack(q);
            else if (interruptible && q.interruptControl < 0) {
                q.thread = null;
                cleanStack();
                return null;
            }
            else if (q.thread != null && result == null) {
                try {
                	// 假设线程不为空,并且没有返回结果。就是线程执行慢要进行阻塞了
                    ForkJoinPool.managedBlock(q);
                } catch (InterruptedException ie) {
                    q.interruptControl = -1;
                }
            }
        }
        if (q != null) {
            q.thread = null;
            if (q.interruptControl < 0) {
                if (interruptible)
                    r = null; // report interruption
                else
                    Thread.currentThread().interrupt();
            }
        }
        postComplete();
        return r;
    }

public static void managedBlock(ManagedBlocker blocker)
        throws InterruptedException {
        ForkJoinPool p;
        ForkJoinWorkerThread wt;
        Thread t = Thread.currentThread();
        //当前测试线程是Main,直接分析else
        if ((t instanceof ForkJoinWorkerThread) &&
            (p = (wt = (ForkJoinWorkerThread)t).pool) != null) {
        }
        else {
            //当前blocker就是上面传参q,直接分析q类型里面的这些方法
            do {} while (!blocker.isReleasable() &&
                         !blocker.block());
        }
    }
    
public boolean block() {
		//false
       if (isReleasable())
           return true;
        //构造赋值时为0.
       else if (deadline == 0L)
           /**
           this对象就是 q,阻塞的就是当前线程。
           到这就找到了如何阻塞线程,那么他是如何定位该线程并唤醒的呢?
           */
           LockSupport.park(this);
       else if (nanos > 0L)
           LockSupport.parkNanos(this, nanos);
       return isReleasable();
   }

public boolean isReleasable() {
        if (thread == null)
            return true;
            //是否被中断
        if (Thread.interrupted()) {
            int i = interruptControl;
            interruptControl = -1;
            if (i > 0)
                return true;
        }
        //构造时,有赋值。已当前分析,不进入
        if (deadline != 0L &&
            (nanos <= 0L || (nanos = deadline - System.nanoTime()) <= 0L)) {
            thread = null;
            return true;
        }
        return false;
    }
       

CompletableFuture 异步操作和源码解读_waitingget_木加子的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值