Java线程池
前置知识:
Java线程请参考:
Java线程详解:线程模型,Thread类,异常处理器,异步执行结果Future阻塞队列请参考:CAS与锁的应用之:原子类、LongAdder、阻塞队列详解
什么是线程池
线程池是一种线程资源,我们通过把线程池化,可以带来许多好处
线程池的好处
- 创建/销毁线程需要消耗系统资源,线程池可以复用已创建的线程
- 控制并发的数量。并发数量过多,可能会导致资源消耗过多,从而造成服务器崩溃。(主要原因)
- 可以对线程做统一管理、监控、调优。
线程池的应用非常丰富,随便翻开一个开源项目都能看到线程池的身影。
Java线程池快速开始
public static void main(String[] args) {
// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i {
System.out.println(1);
});
}
// 关闭线程池
executor.shutdown();
// 等待所有任务完成
while (!executor.isTerminated()) {
}
System.out.println("线程池所有任务完成");
}
线程池的创建方式
阿里规约禁止工程项目通过Executors工具类创建线程池,但规矩是死的人是活的,实际上像dubbo源码中也用到了Executors创建的线程池,但足以见得ThreadPoolExecutor的重要性。
那现在的问题是:Java如何做到池化线程资源?我们知道一个线程只能被调用一次start方法,那么线程在执行完一个线程后,如何执行下一个任务?没有任务时线程就一直消耗资源吗?我们来扒一扒ThreadPoolExecutor源码
Java线程池体系结构
Java中的线程池顶层接口是Executor
接口,ThreadPoolExecutor
是这个接口的核心实现类, 我们从上往下慢慢看。
Executor接口
public interface Executor {
// 执行任务 Runnable是我们封装的线程体,是一段可执行的方法
void execute(Runnable command);
}
Executor往下走是ExecutorService
ExecutorService
public interface ExecutorService extends Executor {
// 关闭线程池
void shutdown();
// 返回未完成任务的列表
List shutdownNow();
boolean isShutdown();
boolean isTerminated();
// 提供了3种submit,返回值都是Future
Future submit(Callable task);
// 共4种invoke 支持超时时间
List invokeAll(Collection