线程池ExecutorService
线程池状态
ThreadPoolExecutor使用int的高3位来表示线程池状态,低29位表示线程数量
状态 | value | 说明 |
---|---|---|
RUNNING(当线程池创建出来的初始状态) | 111 | 能接受任务,能执行阻塞任务 |
SHUTDOWN(调用shutdown方法) | 000 | 不接受新任务,能执行阻塞任务 肯定可以 執行正在執行的任務 |
STOP(调用shutDownNow) | 001 | 不接受新任务,打断正在执行的任务,丢弃阻塞任务 |
TIDYING(中间状态) | 010 | 任务全部执行完,活动线程也没了 |
TERMINATED(终结状态) | 011 | 线程池终结 |
构造方法(参数最多)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
1、核心线程数
2、最大线程数(应急线程数||空闲线程)
3、针对空闲线程的存活时间 如果超时了则把空闲的线程kill
4、针对3的时间单位
5、任务存放的队列
6、线程工厂,主要是产生线程---作用主要是给线程起个自定义名字
7、拒绝策略
工作方式
线程池中刚开始没有线程,当一个任务提交给线程池后,线程池会创建一个新线程来执行任务
当线程数达到 核心线程数上限,这时再加入任务,新加的任务就会被加入队列当中去
前提是有界队列,任务超过了队列大小时,会创建maximumPoolSize - corePoolSize数目的线程数目作为空显线程来执行任务
如果线程达到maximumPoolSize 仍然有新任务这时会执行拒绝策略
工厂方法
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactorythreadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
ExecutorService executorService = Executors.newFixedThreadPool(n);
核心线程数==最大线程数(没有救急线程被创建),因此也无需超时时间
阻塞队列是无界的,可以放任意数量的任务
使用于任务量已知,相对耗时的任务
newCachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
ExecutorService executorService = Executors.newCachedThreadPool()
核心线程数是0,最大线程数是Integer.MAX_VALUE,全部都是空闲线程,60s后回收
一个可根据需要创建新线程的线程池,如果现有线程没有可用的,则创建一个新线程并添加到池中,如果有被使用完但是还没销毁的线程,就复用该线程。终止并从缓存中移除那些已有60秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。
这种线程池比较灵活,对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。
newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
ExecutorService executorService = Executors.newSingleThreadExecutor();
希望多个任务排队执行,线程数固定为1,任务书多于1时,会放入无界队列排队,任务执行完毕后,这唯一的线程也不会被释放。
区别于自己创建一个单线程串行执行任务,如果任务执行失败而终止那么没有任何补救措施,而线程池还会创建一个线程,保证池的正常任务。
Executors.newSingleThreadExecutor()线程个数始终为1,且不能修改,
Executors.newFixedThreadPool(1) 初始时为1,以后还可以修改,对外暴露的是ThreadPoolExecutor对象,可以强转后调用setCorePoolSize等方法进行修改;
提交任务
提交一个任务
void execute(Runnable command);
提交一个任务 <有返回值>
Future<?> submit(Runnable task);
提交所有的任务
List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
提交 tasks 中所有任务,哪个任务先成功执行完毕,返回此任务执行结果,其它任务取消
T invokeAny(Collection<? extends Callable<T>> tasks) throws
InterruptedException, ExecutionException;
shutdown相关
线程池状态变为SHUTDOWN
不会接收新任务
但已提交任务会执行完
不会阻塞调用线程的执行
void shutdown();
线程池状态变为 STOP
不会接收新任务
会将队列中的任务返回
并用 interrupt 的方式中断正在执行的任务
List<Runnable> shutdownNow();
调用 shutdown后,调用线程并不会等待所有任务运行结束,可以利用此方法等待
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;