美文网首页
Executor框架

Executor框架

作者: 叫我民哥L | 来源:发表于2018-09-12 00:47 被阅读0次

    Executor框架简介

    Executor框架的两级调度模型

    Java多线程程序通常把应用分解为若干个任务,然后使用用户级的调度器(Executor框架)将这些任务映射为固定数量的线程;在底层,操作系统内核将这些线程映射到硬件处理器上。被称为两级调度模型。

    Executor框架的结构与成员

    1. Executor框架的结构
      Executor框架主要由3大部分组件组成:
    • 任务: 包括被执行任务需要实现的接口:Runnable接口或Callable接口
    • 任务的执行。包括任务执行机制的核心接口Executor,以及继承自Executor的ExecutorService接口。Executor框架有两个关键实现类实现了ExecutorService接口,ThreadPoolExecutorScheduledThreadPoolExecutor
      下面是这些类和接口的简介:
    • Executor是一个接口,它是Executor框架的基础,它将任务的提交与任务的执行分离
    • ThreadPoolExecutor是线程池的核心实现类,用来执行被提交的任务
    • ScheduledThreadPoolExecutor是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令。功能类似 于Timer,但比Timer更灵活,功能更强大
    • Future接口和实现Future接口的FutureTask类,代表异步计算的结果
      Runnable接口和Callable接口的实现类,都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor执行

    ThreadPoolExector详解

    关于ThreadPoolExector的4个组件构成已经在java线程池实现原理中介绍过,在此不再重复,下面介绍通过Exectors框架的工具类Exectors可以创建的3种类型的ThreadPoolExector:

    • FixedThreadPool
    public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }
    

    FixedThreadPool的corePoolSize和maximumPoolSize都被设置为创建FixedThreadPool时指定的参数nThreads。
    当线程池中的线程数大于corePoolSize时,keepAliveTime为多余的空闲线程等待新任务的最长时间,超过这个时间后多余的线程将被终止。这里把keepAliveTime设置为0L,意味着多余的空闲线程会被立即终止。
    FixedThreadPool使用无界队列LinkedBlockingQueue作为线程池的工作队列(队列的容量为Integer.MAX_VALUE)。使用无界队列作为工作队列会对线程池带来如下影响。

    1. 当线程池中的线程数达到corePoolSize后,新任务将在无界队列中等待,因此线程池中线程数不会超过corePoolSize。
    2. 由于1,使用无界队列时maximumPoolSize将是一个无效参数。
    3. 由于1和2,使用无界队列时keepAliveTime将是一个无效参数。
    4. 由于使用无界队列,运行中的FixedThreadPool(未执行shutDown()或shutDownNow())不会拒绝任务(不会调用RejectedExecutionHandler.rejectedExecution方法)
    • SingleThreadExecutor
      SingleThreadExecutor是使用单个worker线程的Executor。
    public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
    

    SingleThreadExecutor的corePoolSize和maximumPoolSize被设置为1.其他参数与FixedThreadPool相同。所以SingleThreadExecutor使用无界队列作为工作队列对线程池带来的影响与FixedThreadPool相同。

    • CachedThreadPool
      CachedThreadPool是一个会根据需要创建新线程的线程池。
    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
        }
    

    CachedThreadPool的corePoolSize被设置成0,即corePoolSize为空;maximumPoolSize被设置为Integer.MAX_VALUE,即maximumPool是无界的。这里把keepAliveTime设置为60L,意味着CachedThreadPool中的空闲线程等待任务的最长时间为60s,空闲线程超过60s后将会被终止。
    CachedThreadPool使用没有没有容量的SynchronousQueue作为线程池工作队列,但CachedThreadPool的maximumPool是无界的。这意味着,如果主线程提交任务的速度高于maximumPool中线程处理任务的速度时,CachedThreadPool就会不断地创建新任务。极端情况下,CachedThreadPool会因为创建过多线程而耗尽CPU和内存资源。

    In The End

    对比
    corePoolSize maximumPoolSize workQueue keepAliveTime 特点
    FixedThreadPool nTread nTread LinkedBlockingQueue 0 不会拒绝任务
    SingleThreadExecutor 1 1 LinkedBlockingQueue 0 只有单个worker线程
    CachedThreadPool 0 Integer.MAX_VALUE SynchronousQueue 60 使用阻塞队列; maximumPoolSize无界
    适用场景

    FixedThreadPool:由于FixedThreadPool使用无界队列,所以不会拒绝任务。因此合理设置corePoolSize数量配合任务队列,适用于负载比较重的服务器。
    SingleThreadExecutor:SingleThreadExecutor只有一个worker线程,所以提交到SingleThreadExecutor的任务会保证顺序的执行,因此SingleThreadExecutor适用于需要保证顺序的执行任务,并且整个生命周期不会有多个线程的场景。
    CachedThreadPool:CachedThreadPool时大小无界的线程池,因此适用于执行很多短期异步任务的小程序,或者是负载较轻的服务器。

    相关文章

      网友评论

          本文标题:Executor框架

          本文链接:https://www.haomeiwen.com/subject/ucjviftx.html