Executor源码解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/carson0408/article/details/80260097

        任务执行有两种方案,一种是串行执行任务,第二种就是为每个任务创建一个线程;串行执行的问题在于其糟糕的响应性和吞吐量,而后者的问题在于资源管理的复杂性,为每个任务分配一个线程会出现耗内存甚至系统崩溃的问题。因此引入了线程池的概念为合理缓解两者存在的问题。而线程池通过实现Executor框架中的接口来进行工作,首先来看下图的Executor框架的接口以及类的结构图:


        如上图所示,首先是一个最顶层的一个接口:Executor,然后通过继承该接口或者实现该接口进行扩展线程池的具体功能。

1.Executor接口

        Executor接口是一个最顶层的接口,为异步任务执行框架提供了基础,该框架能够支持多种不同类型的任务执行策略,主要有一个抽象方法:execute(Runnable command),主要用于将任务的提交过程与执行过程解耦开来,并用Runnable来表示任务。具体代码如下:

public interface Executor {

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

Executor类族是基于生产者-消费者思想设计的,提交任务相当于生产者生产任务,而执行任务相当于消费者消费任务。

2.ExecutorService接口

        为了解决执行服务的生命周期问题,Executor扩展了ExecutorService接口,添加了一些用于生命周期管理的方法。

    void shutdown();

   
    List<Runnable> shutdownNow();

    
    boolean isShutdown();


    boolean isTerminated();

shutdown方法将执行平缓的关闭过程:不再接受新的任务,并且等待已经提交的任务完成。shutdownNow方法则表示立即关闭。而isShutdown和isTerminated则表示判断是否关闭或者终止。

还有三个submit方法,用于提交的任务,可以用Runnable作为任务,也可以用Callable作为任务。

        一般线程池可以创建ExecutorService对象,创建线程池不是直接使用对象声明方式创建线程池,而是通过一个工厂类Executors中的几个静态方法进行创建满足不同需求的线程池。

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }
 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }
1.newFixedThreadPool:固定长度线程池,每当提交任务创建一个线程,直到线程池的最大数量,该方法返回的是ExecutorService对象,可以看          出该方法调用了ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,

                                      new     LinkedBlockingQueue<Runnable>()),其中第一个参数表示核心线程数,即初始化创建的线程数;第二个参数      是如果最大线程数,即当任务比较多的时候,会自动增加线程数,但不得超过该值;第三个参数表示等待时间,当超过该          时间线程没收到任务则会收回线程;第四个参数是第三个参数的单位;最后一个参数是一个阻塞队列,用于存放工作任务。

2.newSingleThreadExecutor:单线程,这里调用了Executors工厂类的静态方法newSingleThreadExecutor,创建ThreadPoolExecutor对象           时,将线程数限制在1即可。其它如固定长度线程池,只不过是最多只有一个线程工作。

3.newCachedThreadPool:创建一个可缓存的线程池,如果线程池规模过大,回收空闲线程,如果需求增加,则添加新的线程。返回的是new                                             ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,

                                      new SynchronousQueue<Runnable>());从返回的对象可以看出,线程初始值是0,最大值是Integer.MAX_VALUE,                                                 所以能够使得线程数是动态变化的。

4.newScheduledThreadPool:创建固定长度的线程池,以延迟或定时的方式来执行任务,返回ScheduledThreadPoolExecutor对象


通过以上四种静态方法构造的线程池中,主要涉及到两个线程池类,一个是ScheduledThreadPoolExecutor,一个是ThreadPoolExecutor。现在来分析一下这两个类,首先是ThreadPoolExecutor类:

public class ThreadPoolExecutor extends AbstractExecutorService {

该类继承了AbstractExecutorService抽象类,而AbstractExecutorService实现了ExecutorService接口,所以ThreadPoolExecutor属于ExcertorService接口族下的类,因此以上前几个静态方法返回的是ExecutorService对象,符合多态的特点。

ScheduledThreadPoolExecutor实现了ScheduledExecutorService接口,而ScheduledExecutorService接口继承了ExecutorService接口。


总的来说,Executor为了解决多线程任务调度的问题,可以合理平衡系统吞吐量与内存管理。Executor是一个最顶层的接口,为了更好管理Executor的生命周期,便扩展了ExceutorService接口,该类有具体实现类ThreadPoolExecutor和ScheduledExecutorService。并通过工厂类Executors的几个静态方法来创建不同功用的线程池。


猜你喜欢

转载自blog.csdn.net/carson0408/article/details/80260097
今日推荐