0%

线程池

线程池的优点:

  1. 线程复用节省开销,从而加快响应速度

  2. 方便管理(如控制最大并发数)

核心:三大方法,七大参数,四种拒绝策略

三大方法

1
2
3
4
5
6
7
8
9
ExecutorService threadPool=

Executors.newSingleThreadExecutor();//单线程的线程池
Executors.newFixedThreadPool(5);//固定(Fixed)线程的线程池
Executors.newCachedThreadPool();//缓存线程池(可以自己调整)

threadPool.execute(()->{
//具体执行代码
});

七大参数

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
27
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
//从源码中可以看到,三大方法的本质是new ThreadPoolExecutor()

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,//超时未调用则释放
TimeUnit unit,//超时单位
BlockingQueue<Runnable> workQueue//"等候区",可以用构造方法自定义大小
ThreadFactory threadFactory,//一般使用Executors.defaultThreadFactory()
RejectedExecutionHandler handler//拒绝处理策略) {
...
}

以银行取钱的例子说明七大参数

  1. 如果阻塞队列(等候区)满了,则增加poolSize,直到maximumPoolSize

  2. 如果仍满,则触发拒绝策略RejectedExucutionHandler

  3. 如果增开的线程区(core ~ max)在keepAliveTime内没有业务,则关闭,释放资源

.image-20220211110430174

最大承载线程数 = 最大线程数 + 阻塞队列大小

阿里巴巴开发手册

.image-20220211103101062

四种拒绝策略

1
2
3
4
new ThreadPoolExecutor.AbortPolicy()//默认策略, 抛出 RejectedExecutionException 异常
new ThreadPoolExecutor.DiscardPolicy()//直接丢弃超出的线程,但不抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy()//丢弃阻塞队列最前面的线程:poll(),执行超出的线程
new ThreadPoolExecutor.CallerRunsPolicy()//哪里来的回哪里执行

CPU密集型 & IO密集型

最大线程数到底该如何定义?这和调优相关

CPU密集型

最大线程数 = CPU核数(Runtime.getRuntime().availableProcessors()),使CPU效率拉满

IO密集型

最大线程数 > 程序中十分耗IO的线程数