Executor是一套线程池管理框架。是JDK 1.5中引入的一系列并发库中与Executor相关的功能类,其中最核心的类就是常见的ThreadPoolExecutor。
1、工作任务:就是Runnable/Callable接口的实现,可以被线程池执行;
2、异步计算结果:Future接口。实现Future接口的FutureTask类,代表异步处理结果;
3、 执行机制:
Executor
接口:只有一个execute()方法;
ExecutorService
接口:ExecutorService扩展了Executor接口,增加了生命周期的管理方法。
ExecutorService的生命周期包括三种状态:运行、关闭、终止。
创建后便进入运行状态,当调用了shutdown()方法时,便进入关闭状态,此时意味着ExecutorService不再接受新的任务,但它还在执行已经提交了submit()的任务,当已经提交了的任务执行完后,便到达终止状态。
ScheduledExecutorService
接口:任务调度的线程池实现,可以在给定的延迟后运行命令或者定期执行命令;
ThreadPoolExecutor
:最核心的线程池实现,用来执行被提交的任务;
Executor是线程池的顶级接口,接口中只定义了一个方法 void execute(Runnable command);线程池的操作方法都是定义子在ExecutorService子接口中的,所以说ExecutorService是线程池真正的接口。
ThreadPoolExecutor提供了四个构造方法,来看下重要参数:
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {}
参数含义如下:
corePoolSize:线程池核心线程数
maximumPoolSize:线程池最大数
keepAliveTime:空闲线程存活时间
unit:时间单位
workQueue:线程池所使用的缓冲队列
threadFactory:线程池创建线程使用的工厂
handler:线程池对拒绝任务的处理策略
线程池的生命周期,总共有五种状态:
RUNNING(111) :能接受新提交的任务,并且也能处理阻塞队列中的任务;
SHUTDOWN(000):关闭状态,不再接受新提交的任务,但却可以继续处理阻塞队列中已保存的任务。在线程池处于 RUNNING 状态时,调用 shutdown()方法会使线程池进入到该状态。(finalize() 方法在执行过程中也会调用shutdown()方法进入该状态);
STOP(001):不能接受新任务,也不处理队列中的任务,会中断正在处理任务的线程。在线程池处于 RUNNING 或 SHUTDOWN 状态时,调用 shutdownNow() 方法会使线程池进入到该状态;
TIDYING(010):如果所有的任务都已终止了,workerCount (有效线程数) 为0,线程池进入该状态后会调用 terminated() 方法进入TERMINATED 状态。
TERMINATED(011):在terminated() 方法执行完后进入该状态,默认terminated()方法中什么也没有做。
ThreadPoolExecutor 使用int的高三位表示线程池状态,低29位表示线程数量;
Executors类
提供了一系列工厂方法用于创建线程池:
1、public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。
2、public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线 程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
3、public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。
4、public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
1、如果运行线程数小于corePoolSize,那么马上创建线程运行这个任务;
2、如果正在运行的线程数大于等于corePoolSize,那么将这个任务放进队列;
3、如果队列放满了,如果正在运行的线程数小于maximumPoolSize,创建线程处理任务;
4、如果队列放满了,正在运行的线程数大于等于maximumPoolSize,那么线程会抛出异常;RejectExecutionException,执行拒绝策略。
1、AbortPolicy :直接抛出异常,阻止系统运行(线程池默认的拒绝策略);
2、CallerRunsPolicy:由调用线程处理;
3、DiscardPolicy:丢弃无法处理的任务,不予任何处理;
4、DiscardOldestPolicy:丢弃最老的一个请求,也就是即将被执行的一个任务,重新提交被拒绝的任务。
小结:Java线程池中两种提交任务的方法submit() 和 execute()有什么区别? 两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中。而submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口,其它线程池类像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法。