Executor框架

Executor框架简介

Eexecutor框架是一个灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务的线程相当于消费者,并用Runnable来表示任务,Executor的实现还提供了对生命周期的支持,以及统计信息收集,应用程序管理机制和性能监视等机制。

Executor框架的组成

  • 任务: 被执行任务需要实现的接口:Runnable接口或Callable接口。它们的实现类都可以被ThreadPooleExecutor或ScheuledThreadPoolExecutor执行。它们之间的区别是Runnable不会返回结果,而Callable可以返回结果。
  • 任务的执行:
    • Executor接口:执行任务的核心接口,它是Executor框架的基础。
    • ExecutorService接口:继承自Executor。
    • AbstractExecutorService抽象类,实现了ExecutorService接口,提供了执行方法的默认实现。
    • ThreadPoolExecutor:继承了AbstractExecutorService抽象类,是线程池的核心实现类,平时使用最多的就是这个。
    • ScheduledThreadPoolExecutor:继承自ThreadPoolExecutor,可以在给定的延迟后运行命令,或者定期执行命令。
  • 异步计算的结果:
    • Future接口。
    • 继承自Future的FutureTask。

Executor框架的使用示意图
Executor框架的使用示意图

Executor框架的两级调度模型
在HotSpot VM的线程模型中,Java线程被一对一映射为本地操作系统线程。Java线程启动时会创建一个本地操作系统线程;当该Java线程终止时,这个操作系统线程也会被回收。操作系统会调度所有线程并将它们分配给可用的CPU。
Executor框架的两级调度模型

Executors工厂类提供的主要接口

Executor框架最核心的类是ThreadPoolExecutor,它是线程池的实现类。通过Executor框架的工具类Executors,可以方便创建出不同类型的ThreadPoolExecutor和ScheduledThreadPoolExecutor。

1、创建固定线程数FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads)

2、创建单个线程的SingleThreadExecutor
public static ExecutorService newSingleThreadExecutor()

3、创建可缓存线程的线程池CachedThreadPool
public static ExecutorService newCachedThreadPool()

4、创建包含多个线程的ScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

5、创建只包含一个线程的SingleThreadScheduledExecutor
public static ScheduledExecutorService newSingleThreadScheduledExecutor()

6、将一个Runable包装成Callable
public static Callable<Object> callable(Runnable task)

7、将一个Runable和一个待返回的结果包装成一个Callable
public static <T> Callable<T> callable(Runnable task, T result)

通过Executors工具类可以创建3种类型的ThreadPolExecutor,下面分别看下其源码实现:

1、FixedThreadPool源代码实现

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

参数corePoolSize和maximumPoolSize相等且等于初始化的nThreads大小,keepAliveTime=0L代表多余的空闲线程会被立即终止。FixedThreadPool使用无界队列LinkedBlockingQueue作为线程池的工作队列,带来的影响如下:

  • 1)当线程中的线程数达到corePoolSize后,新任务将在无界队列中等待
  • 2)maximumPoolSize和keepAliveTime将是一个无效参数
  • 3)运行中的FixedThreadPool不会决绝任务

2、SingleThreadExecutor源码实现

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

参数corePoolSize和maximumPoolSize相等且为1。SingleThreadExecutor使用无界队列作为工作队列对线程池带来的影响与FixedThreadPool相同

3、CachedThreadPool源码实现

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

参数corePoolSize等于0,maximumPoolSize等于Integer.MAX_VALUE。CachedThreadPool使用没有容量的SynchronousQueue作为线程池的工作队列,但是maximumPool是无界的。带来的影响如下: 如果主线程提交任务的速度高于maximumPool中线程处理任务的速度,CachedThreadPool会不断创建新线程。极端情况下,CachedThreadPool会因为创建过多线程而耗尽CPU和内存资源。

参考资料
Java并发编程的艺术 方腾飞 魏鹏 程晓明 著


------------本文结束感谢您的阅读------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值