线程池
一种线程使用模式,过多的线程会带来调度开销,影响整体性能。线程池内部维护有线程,等待分发任务,避免创建和销毁切换线程带来的消耗。
线程池的优点
- 降低资源消耗,无需频繁的创建销毁线程。
- 提高响应速度,当任务到达时,无需等待线程创建,可立即执行任务。
- 提高线程的可管理性,可以对线程进行统一的监控,调优,分配。
线程池的架构
基于java中的executor实现
几种常见的线程池
-
固定长度线程池
FixedThreadPool, 线程池中有一定量的线程。其中的线程可以被重复使用。超出线程数量的任务被等待。 -
单一线程池
SingleThreadExecutor 只维护了一个线程 -
可变数量线程池
CachedThreadPool 根据任务数量增加/减少线程的数量。
线程池的创建方式
// 演示常见的3种线程池
// 一池多线程
private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
// 一池一线程
private static ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
// 可扩容线程池
private static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
public static void main(String[] args) {
try {
// 十个顾客请求5个窗口
for (int i = 0; i < 100; i++) {
cachedThreadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 正在办理业务");
});
}
} finally {
// 放回线程,供其他任务使用
cachedThreadPool.shutdown();
}
}
线程池的核心参数
几种线程池都通过newThreadPool() 来创建线程池
- corePoolSize 核心/常驻线程数量
- maxPoolSize 最大线程数量
- keepAliveTime 线程存活时间
- unit 线程存活时间单位
- workQueue 阻塞队列,当任务数量超过最大线程数,需要等待
- threadFactory 线程工厂用于生产线程
- handler 拒绝策略,任务过多时直接拒绝
线程池工作流程
自定义线程池
实际中不适用Executors取创建线程池,其创建的线程池默认请求最大长度为Integer.MAX_VALUE,可能会堆积大量的请求,导致OOM
// 自定义线程池
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
2,
10,
2l,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
try {
// 十个顾客请求5个窗口
for (int i = 0; i < 200; i++) {
threadPoolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 正在办理业务");
});
}
} finally {
// 放回线程,供其他任务使用
threadPoolExecutor.shutdown();
}
}