Java的线程既是工作单元,也是执行机制
从JDK 5开始,把工作单元与执行机制分离开来:
- 工作单元包括Runnable和Callable
- 执行机制由Executor框架提供
Java线程被一对一映射为本地操作系统线程
在上层,Java多线程程序通常把应用分解为若干个任务,然后使用用户级的调度器(Executor框架)将这些任务映射为固定数量的线程;在底层,操作系统内核将这些线程映射到硬件处理器上
框架主要成员:
ThreadPoolExecutor:使用工厂类Executors来创建,可创建以下三种类型
FixedThreadPool:适用于为了满足资源管理的需求而需要限制当前线程数量的应用场景,它适用于负载比较重的服务器
SingleThreadExecutor:适用于需要保证顺序地执行各个任务且在任意时间点不会有多个线程是活动的应用场景
CachedThreadPool:大小无界的线程池,适用于执行很多的短期异步任务的小程序或是负载较轻的服务器
ScheduledThreadPoolExecutor:使用工厂类Executors来创建,可创建以下两种类型
ScheduledThreadPoolExecutor:适用于需要多个后台线程执行周期任务,同时为了满足资源管理的需求而需要限制后台线程的数量的应用场景
SingleThreadScheduledExecutor:适用于需要单个后台线程执行周期任务,同时需要保证顺序地执行各个任务的应用场景
Future接口:Future接口和实现Future接口的FutureTask类用来表示异步计算的结果(FutureTask实现了Runnable,可创建FutureTask然后交给ExecutorService执行)
Runnable和Callable接口:
被称为可重用固定线程数的线程池,corePoolSize和maximumPoolSize都被设置为创建FixedThreadPool时指定的参数nThreads
如果当前运行的线程数少于corePoolSize,则创建新线程来执行任务
在线程池完成***预热(当前运行的线程数等于corePoolSize)***之后,将任务加入LinkedBlockingQueue,使用该无界队列带来的影响:
线程执行完任务后,会在循环中反复从LinkedBlockingQueue获取任务来执行
使用单个worker线程的Executor,corePoolSize和maximumPoolSize被设置为1
如果当前运行的线程数少于corePoolSize(即线程池中无运行的线程),则创建一个新线
程来执行任务
在线程池完成预热(当前线程池中有一个运行的线程)之后,将任务加入LinkedBlockingQueue,,使用该无界队列带来的影响参考上一小节
线程执行完任务后,会在循环中反复从LinkedBlockingQueue获取任务来执行
会根据需要创建新线程的线程池,corePoolSize被设置为0(即corePool为空),maximumPoolSize被设置为Integer.MAX_VALUE(即线程池无界)
下述流程和上面两个线程池的区别主要是因为CachedThreadPool使用SynchronousQueue,该队列是没有容量的阻塞队列(即每个插入操作必须等待另一个线程的对应移除操作)
首先执行SynchronousQueue.offer
,如果当前maximumPool中有空闲线程正在执行SynchronousQueue.poll
,则主线程把任务交给空闲线程执行
如果初始maximumPool为空或maximumPool中当前没有空闲线程时,将没有线程执行
SynchronousQueue.poll
,此时CachedThreadPool会创建一个新线程执行任务
新创建的线程将任务执行完后,会执行SynchronousQueue.poll
(该操作会让空闲线程最多等待60秒钟),如果60秒钟内主线程提交了一个新任务,则这个空闲线程将执行新任务;否则该空闲线程将终止(长时间保持空闲的CachedThreadPool不会使用任何资源)
主要用来在给定的延迟之后运行任务或定期执行任务
Timer对应的是单个后台线程,ScheduledThreadPoolExecutor可以在构造函数中指定多个对应的后台线程数
Future接口和实现Future接口的FutureTask类代表异步计算的结果
FutureTask除了实现Future接口外,还实现了Runnable接口(因此可交给Executor执行,也可以由调用线程直接执行,即执行FutureTask.run
)
根据FutureTask.run
被执行的时机,FutureTask可处于下面3种状态:
FutureTask.cancel
)或抛异常,FutureTask处于已完成状态FutureTask中get方法和cancel方法的执行如下: