AbstractExecutorService源码解读

AbstractExecutorService

invokeAll

// 执行完成tasks中所有的任务,如果有一个抛出异常,则取消掉剩余的任务
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException {
        if (tasks == null)
            throw new NullPointerException();
  		// 创建一个添加任务的集合
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
          	// 遍历tasks中的任务将其转换成RunnableFuture,然后提交到线程池执行
            for (Callable<T> t : tasks) {
                RunnableFuture<T> f = newTaskFor(t);
                futures.add(f);
                execute(f);
            }
            for (int i = 0, size = futures.size(); i < size; i++) {
                Future<T> f = futures.get(i);
              	// 判断任务是否执行完成,如果没有执行完,取出进行等待执行完毕
                if (!f.isDone()) {
                    try {
                        f.get();
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    }
                }
            }
          	// 所有任务执行完毕
            done = true;
            return futures;
        } finally {
            if (!done)
              	// 如果任务执行发生异常,取消所有任务的执行
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }
 }
// 逻辑同上,不过加了等待时间,如果超过等待时间,则进行返回
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                         long timeout, TimeUnit unit)
        throws InterruptedException {
        if (tasks == null)
            throw new NullPointerException();
        long nanos = unit.toNanos(timeout);
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            for (Callable<T> t : tasks)
                futures.add(newTaskFor(t));
            final long deadline = System.nanoTime() + nanos; // 等待时间
            final int size = futures.size();

            for (int i = 0; i < size; i++) {
                execute((Runnable)futures.get(i));
                // 执行每个任务后剩余的时间
                nanos = deadline - System.nanoTime(); 
                if (nanos <= 0L)
                	// 超出等待时间直接返回任务
                    return futures; 
            }

            for (int i = 0; i < size; i++) {
                Future<T> f = futures.get(i);
                if (!f.isDone()) { // 任务未执行
                    if (nanos <= 0L)
                    	// 等待超时
                        return futures; 
                    try {
                    	// 等待任务执行完毕
                        f.get(nanos, TimeUnit.NANOSECONDS); 
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    } catch (TimeoutException toe) {
                        return futures;
                    }
                     // 每个任务执行完毕重新计算等待时间
                    nanos = deadline - System.nanoTime();
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done) // 发生异常,取消所有任务
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }
}

invokeAny

不带超时时间的

// 多个任务只要有一个执行成功就返回,并把剩余的已提交未执行的任务给取消掉
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException {
        try {
            return doInvokeAny(tasks, false, 0);
        } catch (TimeoutException cannotHappen) {
            assert false;
            return null;
        }
    }

带超时时间的

// 多个任务只要有一个执行成功就返回,并把剩余的已提交未执行的任务给取消掉
// 如果指定时间内没有执行成功的,则抛出TimeoutException 异常
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                       long timeout, TimeUnit unit)
  throws InterruptedException, ExecutionException, TimeoutException {
  return doInvokeAny(tasks, true, unit.toNanos(timeout));
}

doInvokeAny()方法

private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
                              boolean timed, long nanos)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (tasks == null)
            throw new NullPointerException();
        int ntasks = tasks.size();
        if (ntasks == 0)
            throw new IllegalArgumentException();
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
  			// 创建一个接收当前任务对象的队列
        ExecutorCompletionService<T> ecs =
            new ExecutorCompletionService<T>(this);
        try {
            ExecutionException ee = null;
          	// 判断是否设置超时时间
            final long deadline = timed ? System.nanoTime() + nanos : 0L;
            Iterator<? extends Callable<T>> it = tasks.iterator();
						// 提交并执行一个任务
            futures.add(ecs.submit(it.next()));
          	// 任务执行一个,任务数量减一
            --ntasks;
          	// 已执行的任务数量
            int active = 1;

            for (;;) {
              	// 取出最新任务
                Future<T> f = ecs.poll();
                if (f == null) { 
                  	// 没有执行完, 继续添加并执行任务
                    if (ntasks > 0) {
                        --ntasks;
                        futures.add(ecs.submit(it.next()));
                        ++active;
                    }
                    else if (active == 0) // 所有任务都执行失败
                        break;
                    else if (timed) { // 判断是否等待超时
                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
                        if (f == null)
                            throw new TimeoutException();
                      	// 计算剩余等待时间
                        nanos = deadline - System.nanoTime();
                    }
                    else
                        f = ecs.take();
                }
                // 第一个任务执行完毕
                if (f != null) {
                    --active;
                    try {
                    	// 返回第一个任务的执行结果
                        return f.get();
                    } catch (ExecutionException eex) {
                        ee = eex;
                    } catch (RuntimeException rex) {
                        ee = new ExecutionException(rex);
                    }
                }
            }

            if (ee == null)
                ee = new ExecutionException();
            throw ee;

        } finally {
        	// 把其他没执行的任务取消掉
            for (int i = 0, size = futures.size(); i < size; i++)
                futures.get(i).cancel(true);
        }
    }

注意

invokeAny方法可以同时执行多个任务,但最少执行一个任务,拿到最先执行完成任务的结果,要么都不执行。

finally最后取消所有任务都会取消吗

点进去FutureTask cancel()看下
cancel()
我们可以看到state != NEW的时候直接返回false,那么任务是从何而来呢,要么通过构造方法,要么通过set方法,我们可以看FutureTask类的set方法可以看到这里会把已完成任务的状态设置为NORMAL,所以已完成的任务不会被取消。
设置完成任务的状态

ExecutorCompletionService中poll()这里什么时候为null

为什么为null

进入这个poll方法查看发现queue队列poll
poll方法

那么这个队列是什么呢,点开构造方法查看
LinkedBlockingQueue

点进去这个队列查看poll方法
poll

在这里我们可以看到当数量为0时才会返回null,那么是什么时候往这个队列放值呢,其实是在futures添加任务ecs.submit()方法里进行放值的
往队列添加任务

点进去这个队列查看
任务执行完往队列添加

也就是任务执行结束,才会往这个queue里面放值,那么回到上面的ecs.poll()方法,也就是说如果为null的话,任务并没有执行完毕。
那么什么时候会调用done()呢,其实是在FutureTask里面的finishCompletion()里面调用的
finishCompletion
那么谁调用了这个方法呢,在这个方法上查看哪里调用,我们不难发现也就是在添加任务和取消任务的时候都会调用,往completionQueue中添加任务。
调用finishCompletion
cancel()可以看到上面finally代码块调用,set方法什么时候会被调用呢
进入ExecutorCompletionService的submit()方法查看可以看到这里执行任务
在这里插入图片描述
执行任务之后会调用FutureTask里的run()方法
set方法

总结

ecs也就是代理了线程池去执行,包装了FutureTask,让任务执行完毕自己把自己放到队列中,提供了一个阻塞队列查看任务执行完毕了没有。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值