JAVA并发包(六):AbstractExecutorService

接下来我们开始研究激动人心的java并发的核心–线程池,并发包里的很多api都是服务于线程池的,像前面讲到AQS,重入锁,以及后面会讲解的阻塞队列等等,都可以在线程池的源码中看到。由于线程池设计到的api有多个,我这里就一步步来讲,先研究比较简单的AbstractExecutorService。

一、接口关系图

从以下关系图中可以看到,AbstractExecutorService作为抽象执行服务类,实现了ExecutorService接口和顶层的Executor接口。其具体的实现类是ThreadPoolExecotor,它是线程池的核心实现逻辑,后面介绍。另外AbstractExecutorService还关联了FutureTask类,FutureTask是异步返回线程执行结果的具体实现类,后面也会有专门讲解。
在这里插入图片描述

二、源码分析

下面简单分析AbstractExecutorServcie以及上层接口的源码

1.Executor

Executor我叫它做执行者吧,它的源码很简单就一个方法execute(),简单理解就是专门用来执行命令的,你传什么进来,我就不折不扣地执行。这里也可以看到java代码抽象的简洁之道。

public interface Executor {
	execute(Runnable command);
}

2.ExecutorService

ExecutorService接口增加了很多功能方法,它作为服务接口,对外提供这些服务,实现类必须实现这些接口

public interface ExecutorService extends Executor {
	// 关闭线程池,会等待正在执行中的线程执行完
    void shutdown();
	
	// 立刻关闭线程池,如果有正在执行的线程,会被中断
    List<Runnable> shutdownNow();
	
	// 判断线程池是否被关闭了
    boolean isShutdown();
    
    // 判断线程池是否终止了,这是线程池的最终状态
    boolean isTerminated();
    
    // 等待给定时间后终止线程池
    boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;
    
    // 提交一个执行任务,返回一个未来的引用,这个引用可以获取到执行结果
    <T> Future<T> submit(Callable<T> task);
    
    // 提交一个执行任务,返回一个未来的引用,这个引用可获取到结果是传入的参数result
    <T> Future<T> submit(Runnable task, T result);
    
    // 提交一个执行任务,返回一个未来的引用,这个引用可以获取到执行结果,入参跟Callable相比就是入参的范围比较广了,只要实现Runable接口即可
    Future<?> submit(Runnable task);

	// 执行所有传入的任务,等待所有任务结束才返回,结果都在返回的list里面,
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;
	
	// 跟上面方面相比,会有一个时间限制完成所有的任务,如果时间耗尽,有些任务没执行完,则没有结果
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;

	// 返回任意一个执行的结果
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;
	
	// 给定时间内返回任意一个执行结果
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

3.AbstractExecutorService

AbstractExecutorService有线程池的部分实现逻辑,这里能大概看到线程池大体的实现方案,虽然不够详细,但是这里是理解线程池原理的入口。

submit提交任务

	// 这个有返回的结果的提交方法,是比较容易看理解线程池原理的
	public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        // 这里创建了一个Future,我们理解线程执行完后会被结果放到这里
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        // execute是执行任务的方法,可以猜测它会开启一个线程异步处理,然后把结果放到future里面
        execute(ftask);
        return ftask;
    }

	protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }
	
	// 这个有传入结果入参的方法,会把result作为结果放到future里面,所以线程执行完的话,它的结果就是result了,从后面的代码可以看出它的原理
	public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }

	protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

	public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }

	public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
            // 这里使用了适配器,适配成Callable接口
        return new RunnableAdapter<T>(task, result);
    }

	static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            // 这里就是传入的result
            this.result = result;
        }
        public T call() {
            task.run();
            // 这里看出调用call的话会返回刚刚传入的result
            return result;
        }
    }

invokeAll方法解析,等待所有任务完成才返回

	// 这里是执行任务集合的方法
	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 {
            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 {
        	// 最后判断done的值,如果为false说明发生了异常,则取消每个任务的执行,所以最终返回的结果可能是被取消了的,结果可能为null
            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;
        }
    }

	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);
        // 这个类专门用来处理批量有返回的线程,线程返回的future会放到一个阻塞队列里,然后调用take方法获取,后面讲解
        ExecutorCompletionService<T> ecs =
            new ExecutorCompletionService<T>(this);
        try {
            // Record exceptions so that if we fail to obtain any
            // result, we can throw the last exception we got.
            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);
        }
    }

三、总结

AbstractExecutorService是研究线程池原理的入口,这个抽象类中搭起了线程池的原理框架,只要把这个类理解透了,那么研究更细节的代码就会有个所以然的结果。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值