JUC-并发编程16-线程池深入分析-体系结构

1、简介

java的线程池是比较常用的在并发编程里面。对线程池的源码做深入研究不仅能提高对java整个并发编程的理解,也能提高自己在面试中的表现,增加被录取的可能性。

2、体系结构

上图列举了线程池中非常重要的接口和类:

  1. Executor,线程池顶级接口
  2. ExecutorService,线程池次级接口,对Executor的补充,做了一下扩展
  3. ScheduleExecutorService,对ExecutorService做了一些扩展,增加一些定时任务相关的功能;
  4. AbstractExecutorService,抽象类,运用模板方法设计模式实现了一部分方法;
  5. ThreadPoolExecutor,普通线程池类,这也是我们通常所说的线程池,包含最基本的一些线程池相关操作的实现;
  6. ScheduleThreadPoolExecutor,定时任务实现类,用于实现定时任务相关功能;
  7. ForkJoinPool,新型线程池类,java7中新增的线程池类,基于工作窃取理论实现,运用于大任务拆分小任务,任务无限多的场景;
  8. Executors,线程池工具类,定义了一些快速实现线程池的方法(谨慎使用);

3、Executor

线程池顶级接口,只定义了一个执行无返回值的任务方法。

public interface Executor {
    void execute(Runnable command);
}

4、ExecutorService

线程池次级接口,对Executor做了一些扩展,主要增加了关闭线程池、执行有返回值任务、批量执行任务的方法。

public interface ExecutorService extends Executor {

    /**
	 *关闭线程池,不再接受新任务,但是已经提交的任务会执行完成	
     */
    void shutdown();

    /**
     *立即关闭线程池,尝试停止正在运行的任务,未执行任务不再执行
	 *被迫停止及未执行的任务将以列表的形式返回
     */
    List<Runnable> shutdownNow();

    /**
     *检查线程池是否已关闭
     */
    boolean isShutdown();

    /**
     *检查线程池是否已终止,只有在shutdown()或shutdownNow()之后调用才有可能为true
     */
    boolean isTerminated();

    /**
     * 在指定时间内线程池达到终止状态了才会返回true
     */
    boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;

    /**
     * 执行有返回值的任务,任务的返回值true,call()的结果
     */
    <T> Future<T> submit(Callable<T> task);

    /**
     * 执行有返回值的任务,任务的返回值为这里传入的result
	 * 当然只有当任务执行完成了调用get()时才会返回
     */
    <T> Future<T> submit(Runnable task, T result);

    /**
     * 执行有返回值的任务,任务的返回值为null
	 * 当然只有当任务执行完成了调用get()时才会返回
     */
    Future<?> submit(Runnable task);

    /**
     *批量执行任务,只有当这些任务都完成了这个方法才会返回
     */
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;

    /**
     * 在指定时间内批量执行任务,未执行完成的任务将被取消
	 * 这里的timeout是所有任务的总时间,不是单个任务的时间 
     */
    <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;
}

5、ScheduledExecutorService

对ExecutorService做了一些扩展,增加一些定时任务相关的功能,主要包含两大类:执行一次,重复多次执行。

public interface ScheduledExecutorService extends ExecutorService {

    /**
     * 在指定时间段后执行一次 
	 * @throws RejectedExecutionException if the task cannot be scheduled for execution
     *         
     * @throws NullPointerException if command is null
     */
    public ScheduledFuture<?> schedule(Runnable command,
                                       long delay, TimeUnit unit);

    /**
     * 在指定时间段后执行一次 
     * @return a ScheduledFuture that can be used to extract result or cancel
     * @throws RejectedExecutionException if the task cannot be
     *         scheduled for execution
     * @throws NullPointerException if callable is null
     */
    public <V> ScheduledFuture<V> schedule(Callable<V> callable,
                                           long delay, TimeUnit unit);

    /**
     *在指定延时后开始执行,并在之后以指定时间间隔重复执行(间隔不包含任务执行的时间)
     *
     * @return a ScheduledFuture representing pending completion of
     *         the task, and whose {@code get()} method will throw an
     *         exception upon cancellation
     * @throws RejectedExecutionException if the task cannot be
     *         scheduled for execution
     * @throws NullPointerException if command is null
     * @throws IllegalArgumentException if period less than or equal to zero
     */
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit);

    /**
     * 在指定延时后开始执行,并在之后以指定延时重复执行(间隔包含任务执行的时间)
     * @return a ScheduledFuture representing pending completion of
     *         the task, and whose {@code get()} method will throw an
     *         exception upon cancellation
     * @throws RejectedExecutionException if the task cannot be
     *         scheduled for execution
     * @throws NullPointerException if command is null
     * @throws IllegalArgumentException if delay less than or equal to zero
     */
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);

}

6、AbstractExecutorService

抽象类,运用模板方法设计模式实现了一部分方法,主要为执行有返回值任务、批量执行任务的方法。

public abstract class AbstractExecutorService implements ExecutorService {

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


    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }

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

    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

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

        // For efficiency, especially in executors with limited
        // parallelism, check to see if previously submitted tasks are
        // done before submitting more of them. This interleaving
        // plus the exception mechanics account for messiness of main
        // loop.

        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();

            // Start one task for sure; the rest incrementally
            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);
        }
    }

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

    public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                           long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        return doInvokeAny(tasks, true, unit.toNanos(timeout));
    }

    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 {
            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();

            // Interleave time checks and calls to execute in case
            // executor doesn't have any/much parallelism.
            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);
        }
    }

}

这里的submit()方法对传入的任务都包装成了FutureTask来进行处理。

7、ThreadPoolExecutor

普通线程池类,这也是我们通常所说的线程池,包含最基本的一些线程池操作相关的方法实现。线程池的主要实现逻辑都在这里面,比如线程的创建、任务的处理、拒绝策略等,我们后面单独分析这个类。

8、ScheduledThreadPoolExecutor

定时任务线程池类,用于实现定时任务相关功能,将任务包装成定时任务,并按照定时策略来执行,我们后面单独分析这个类。

9、ForkJoinPool

新型线程池类,java7中新增的线程池类,这个线程池与Go中的线程模型特别类似,都是基于工作窃取理论,特别适合于处理归并排序这种先分后合的场景。

10、Executors

线程池工具类,定义了一系列快速实现线程池的方法——newXXX(),不过阿里手册是不建议使用这个类来新建线程池的,其实只要能掌握其源码,知道其利敝偶尔还是可以用的,后面我们再来说这个事。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值