线程池定义
线程池是一个放置线程的容器,其中保留部分存活的线程,以备随时使用,避免了每次使用时都需要创建及销毁线程的耗时操作,同时可以方便统一控制线程的数量,配置线程参数、任务队列、拒绝策略。
推荐的线程池的创建方法
Java 自带的 ThreadPoolExecutor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public ThreadPoolExecutor(
// 核心线程数量
int corePoolSize,
// 最大线程数量
int maximumPoolSize,
// 存活时间
long keepAliveTime,
// 时间单位
TimeUnit unit,
// 任务队列
BlockingQueue<Runnable> workQueue,
// 线程创建工厂
ThreadFactory threadFactory,
// 拒绝策略
RejectedExecutionHandler handler
)
|
| 参数名 |
解释 |
|
| corePoolSize |
核心线程数量,保证存活随时可用的线程数量。CPU 密集型操作,则设置为 CPU核数 + 1;IO 密集型则设置为 CPU核数 * 2 |
|
| maximumPoolSize |
最大线程数量,一般与核心线程数量一致。可基于最大 CPU 利用率、内存利用率、IO 利用率进行限制。 |
|
| keepAliveTime |
线程空闲时间,一般为 60 s |
|
| unit |
一般设置为秒 TimeUnit.SECOND |
|
| workQueue |
等待执行的任务队列。包括无界队列(LinkedBlockingQueue)、有界队列(ArrayBlockingQueue:一般有界队列;PriorityBlockingQueue:优先级阻塞队列)、同步移交队列(没有可用线程时异常)。 |
|
| threadFactory |
线程工厂。可配置线程名称、线程组、优先级、守护进程状态等 |
|
| handler |
队列已满时的拒绝策略。默认实现包括四种:AbortPolicy(丢弃任务,抛出异常)、CallRunsPolicy(由当前调用的任务线程执行)、DiscardPolicy(忽视该任务)、DiscardOldestPolicy(剔除最老的任务) |
|
SpringBoot 中封装的 ThreadPoolTaskExecutor
封装 ThreadPoolExecutor,提供了默认配置参数,简化了线程池的创建。但是仍然建议手动创建,根据实际情况配置其参数。
其他线程池
一般情况下不推荐使用以下线程池, 酌情使用
1
2
3
4
5
6
7
8
9
10
11
|
// 该线程池中只有一个线程
Executors.newSingleThreadExecutor();
// 该线程池不限制线程数量
Executors.newCachedThreadPool();
// 该线程池固定线程数,任务队列采用的无界队列(LinkedBlockingQueue)
Executors.newFixedThreadPool(100);
// 该线程池固定线程数,可执行延迟任务,也可执行带返回值的任务
Executors.newScheduledThreadPool(100);
|
线程池的任务队列
LinkedBlockingQueue
略
ArrayBlockingQueue
略
PriorityBlockingQueue
需要自己实现 Runnable,否则,默认 Comparator 是 null,使用元素的 compareTo 方法进行比较。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// 实现 Runnable
class MyTask implements Runnable {
private int priority;
public int getPriority() {
return priority;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws InterruptedException {
// 创建比较器
Comparator<MyTask> comparator = Comparator.comparingInt(MyTask::getPriority);
// 新建线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,10,1000,TimeUnit.MICROSECONDS,new PriorityBlockingQueue(100, comparator));
}
|