java ThreadPoolExecutor线程池的使用
笔记: java ThreadPoolExecutor线程池的使用
1 为什么使用线程池?
(1) 大量线程的创建和销毁会过度消耗系统资源
(2) 节省系统响应时间, 如果要处理请求, 而线程池中恰好有空闲的线程, 那么就可以直接处理, 无需创建新的线程; 不仅节省了系统资源, 无形中也缩减了响应请求的时间
(3) 控制程序创建线程的数量, 通过设置线程池最大线程数限制线程数量, 防止线程过多导致系统崩溃
2 创建线程池
使用静态代码块创建一个线程池
private static ExecutorService singleThreadPool;
static {
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("demo-pool-%d").build();
singleThreadPool = new ThreadPoolExecutor(
5,
5,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(2048),
namedThreadFactory,
new ThreadPoolExecutor.CallerRunsPolicy());
}
ThreadFactory : 线程工厂
ThreadFactoryBuilder: 使用ThreadFactoryBuilder创建一个带有名字的线程, 便于发生异常时的排查
ExecutorService:
ExecutorService接口继承自Executor接口,提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。
增加了shutDown(),shutDownNow(),invokeAll(),invokeAny()和submit()等方法。如果需要支持即时关闭,也就是shutDownNow()方法,则任务需要正确处理中断。
ThreadPoolExecutor: 一个ExecutorService的实现
构造方法:
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize: 线程池核心线程数
maximumPoolSize: 线程池中允许的最大线程数
keepAliveTime: 线程处于空闲状态时, 多长时间销毁
unit: keepAliveTime的单位
workQueue: 缓存队列, 线程数达到核心线程数时, 任务被放入缓冲队列
threadFactory: 线程工厂
handler: 线程丢弃策略, 当最大线程数达到maximumPoolSize, 并且缓冲队列满, 则触发丢弃策略
ThreadPoolExecutor.AbortPolicy: 抛出java.util.concurrent.RejectedExecutionException异常
ThreadPoolExecutor.CallerRunsPolicy() : 重试添加当前的任务,他会自动重复调用execute()方法
ThreadPoolExecutor.DiscardOldestPolicy() : 抛弃池中存在最久的任务
ThreadPoolExecutor.DiscardPolicy() : 抛弃当前的任务
3 执行任务
只需要调用execute()方法就可以创建新的线程
public void saveData() {
try {
singleThreadPool.execute(new Runnable() {
@Override
public void run() {
// do some
}
});
} catch (Exception e) {
e.printStackTrace();
} finally{
// 由于线程池是在静态代码块中创建的, 这里不能shutdown, 会获取不到线程池实例
// singleThreadPool.shutdown();
}
}