Executor框架两级调度
Java线程启动时会创建一个本地操作系统线程,当该Java线程终止时,这个操作系统线程也会被回收。操作系统会调度所有线程并将它们分配给可用CPU。
在上面的调度模型中:
在上层,Java多线程程序通常把应用分解为若干任务,然后使用用户级的调度器将这些任务映射为固定数量的线程;在底层,操作系统内核将这些线程映射到硬件处理器上。
Executor框架结构
Executor框架由3大部分组成
-
任务
包括被执行任务需要的实现接口(Runnable接口或Callable接口)
Runnable接口和Callable接口的实现类,可以被ThreadPoolExecutor或者ScheduleThreadPoolExecutor -
执行的任务
包括任务执行机制的核心接口**
Executor
以及继承自Executor
的ExecutorService
**接口Executor是一个接口,时Executor框架的基础,它将任务的提交与任务的执行分离
ThreadPoolExecutor是线程池的核心实现类,用来执行被提交的任务
ScheduleThreadPoolExecutor,可以在给定的延迟后运行命令,或者定期执行命令
-
异步计算的框架
包括接口**Future
和实现Future接口的FutureTask
**类,代表异步计算的结果
Executor框架成员
Executor框架主要成员:ThreadPoolExecutor、ScheduledThreadPoolExecutor、Future接口、Runnable接口、Callable接口、Executors。
-
ThreadPoolExecutor
ThreadPoolExecutor通常使用工厂类Executors来创建,Executors可以创建3种类型的ThreadPoolExecutor;分别是SingleThreadExecutor、FixedThreadPool、CachedThreadPool。ThreadPoolExecutor是Executor框架最核心的类,是实现线程池的类。主要由下列组件构成
- corePool:核心线程池大小
- maximumPool:最大线程池的大小
- BlockingQueue:用来暂时保存任务的工作队列
下面分别介绍3种类型的ThreadPoolExecutor:
-
SingleThreadExecutor:
SingleThreadExecutor适用于需要保证顺序执行各个任务;并且在任意时间点,不会有多个线程是活动的应用场景。
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)); }
在上面的代码中,SingleThreadExecutor的corePoolSize和maximumPoolSize被设置为1,SingleThreadExecutor使用无界队列LinkedQueueBlockingQueue作为线程池的工作队列(队列的容量为Integer.MAX_VALUE)。SingleThreadExecutor的运行图如下
下面对上图中的过程进行说明:
1.如果当前运行的线程少于corePoolSize(线程池中没有运行的线程),则创建一个线程类执行任务
2.在线程池完成预热之后,将任务加入LinkedBlockingQueue
3.线程执行完1中的任务后,会在一个无限循环中反复从LinkedBlockingQueue获取任务来执行
-
FixedThreadPool:
FixedThreadPool适用于为了满足资源管理的需求,而需要限制当前线程数量的应用场景。适用于负载均衡比较重的服务器
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); }
FixedThreadPool的corePoolSize和maximumPoolSize都被设置为创建FixedThreadPool时指定的参数nThread
当线程池中的线程数大于corePoolSize时,keepAliveTime为多余的空闲线程等待新任务的最长时间,超过这个时间后多余的线程将被终止。把keepAliveTime设置为0L,说明多余的空闲线程会被立即终止。
1.如果当前运行的线程数少于corePoolSize,则创建线程来执行任务
2.在线程池完成预热后将任务加入LinkedBlockingQueue
3.线程执行完成1中的任务后,会在循环中反复从LinkedBlockingQueue获取任务来执行
FixedThreadPool使用无界队列LinkedBlockingQueue作为线程池的工作队列(队列的容量为Integer.MAX_VALUE)
-
CachedThreadPool
CachedThreadPool是大小无界的线程池,适用于执行很多短期异步任务的小程序或负载较轻的服务器
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); }
CachedThreadPool的corePoolSize被设置为0,maximumPoolSize被设置为Integer.MAX_VALUE,即maximumPool是无界,把keepAliveTime设置为60L,CachedThreadPool中的空闲线程等待新任务的最长时间为60秒,空闲线程超过60秒后将会终止
ScheduleThreadPoolExecutor
待续