@@ -375,45 +375,55 @@ public static class CallerRunsPolicy implements RejectedExecutionHandler {
375
375
这里简单举一个例子,该线程池限定了最大线程数为 2,还阻塞队列大小为 1(这意味着第 4 个任务就会走到拒绝策略),` ThreadUtil ` 为 Hutool 提供的工具类:
376
376
377
377
``` java
378
- Logger log = LoggerFactory . getLogger(ThreadPoolTest . class);
379
- // 创建一个线程池,核心线程数为1,最大线程数为2
380
- // 当线程数大于核心线程数时,多余的空闲线程存活的最长时间为60秒,
381
- // 任务队列为容量为1的ArrayBlockingQueue,饱和策略为CallerRunsPolicy。
382
- ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor (1 ,
383
- 2 ,
384
- 60 ,
385
- TimeUnit . SECONDS ,
386
- new ArrayBlockingQueue<> (1 ),
387
- new ThreadPoolExecutor .CallerRunsPolicy ());
388
-
389
- // 提交第一个任务,由核心线程执行
390
- threadPoolExecutor. execute(() - > {
391
- log. info(" 核心线程执行第一个任务" );
392
- ThreadUtil . sleep(1 , TimeUnit . MINUTES );
393
- });
394
-
395
- // 提交第二个任务,由于核心线程被占用,任务将进入队列等待
396
- threadPoolExecutor. execute(() - > {
397
- log. info(" 非核心线程处理入队的第二个任务" );
398
- ThreadUtil . sleep(1 , TimeUnit . MINUTES );
399
- });
400
-
401
- // 提交第三个任务,由于核心线程被占用且队列已满,创建非核心线程处理
402
- threadPoolExecutor. execute(() - > {
403
- log. info(" 非核心线程处理第三个任务" );
404
- ThreadUtil . sleep(1 , TimeUnit . MINUTES );
405
- });
406
-
407
- // 提交第四个任务,由于核心线程和非核心线程都被占用,队列也满了,根据CallerRunsPolicy策略,任务将由提交任务的线程(即主线程)来执行
408
- threadPoolExecutor. execute(() - > {
409
- log. info(" 主线程处理第四个任务" );
410
- ThreadUtil . sleep(2 , TimeUnit . MINUTES );
411
- });
412
-
413
- // 提交第五个任务,主线程被第四个任务卡住,该任务必须等到主线程执行完才能提交
414
- threadPoolExecutor. execute(() - > {
415
- log. info(" 核心线程执行第五个任务" );
416
- });
378
+ public class ThreadPoolTest {
379
+
380
+ private static final Logger log = LoggerFactory . getLogger(ThreadPoolTest . class);
381
+
382
+ public static void main (String [] args ) {
383
+ // 创建一个线程池,核心线程数为1,最大线程数为2
384
+ // 当线程数大于核心线程数时,多余的空闲线程存活的最长时间为60秒,
385
+ // 任务队列为容量为1的ArrayBlockingQueue,饱和策略为CallerRunsPolicy。
386
+ ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor (1 ,
387
+ 2 ,
388
+ 60 ,
389
+ TimeUnit . SECONDS ,
390
+ new ArrayBlockingQueue<> (1 ),
391
+ new ThreadPoolExecutor .CallerRunsPolicy ());
392
+
393
+ // 提交第一个任务,由核心线程执行
394
+ threadPoolExecutor. execute(() - > {
395
+ log. info(" 核心线程执行第一个任务" );
396
+ ThreadUtil . sleep(1 , TimeUnit . MINUTES );
397
+ });
398
+
399
+ // 提交第二个任务,由于核心线程被占用,任务将进入队列等待
400
+ threadPoolExecutor. execute(() - > {
401
+ log. info(" 非核心线程处理入队的第二个任务" );
402
+ ThreadUtil . sleep(1 , TimeUnit . MINUTES );
403
+ });
404
+
405
+ // 提交第三个任务,由于核心线程被占用且队列已满,创建非核心线程处理
406
+ threadPoolExecutor. execute(() - > {
407
+ log. info(" 非核心线程处理第三个任务" );
408
+ ThreadUtil . sleep(1 , TimeUnit . MINUTES );
409
+ });
410
+
411
+ // 提交第四个任务,由于核心线程和非核心线程都被占用,队列也满了,根据CallerRunsPolicy策略,任务将由提交任务的线程(即主线程)来执行
412
+ threadPoolExecutor. execute(() - > {
413
+ log. info(" 主线程处理第四个任务" );
414
+ ThreadUtil . sleep(2 , TimeUnit . MINUTES );
415
+ });
416
+
417
+ // 提交第五个任务,主线程被第四个任务卡住,该任务必须等到主线程执行完才能提交
418
+ threadPoolExecutor. execute(() - > {
419
+ log. info(" 核心线程执行第五个任务" );
420
+ });
421
+
422
+ // 关闭线程池
423
+ threadPoolExecutor. shutdown();
424
+ }
425
+ }
426
+
417
427
```
418
428
419
429
输出:
@@ -496,7 +506,8 @@ new RejectedExecutionHandler() {
496
506
497
507
- 容量为 ` Integer.MAX_VALUE ` 的 ` LinkedBlockingQueue ` (无界队列):` FixedThreadPool ` 和 ` SingleThreadExector ` 。` FixedThreadPool ` 最多只能创建核心线程数的线程(核心线程数和最大线程数相等),` SingleThreadExector ` 只能创建一个线程(核心线程数和最大线程数都是 1),二者的任务队列永远不会被放满。
498
508
- ` SynchronousQueue ` (同步队列):` CachedThreadPool ` 。` SynchronousQueue ` 没有容量,不存储元素,目的是保证对于提交的任务,如果有空闲线程,则使用空闲线程来处理;否则新建一个线程来处理任务。也就是说,` CachedThreadPool ` 的最大线程数是 ` Integer.MAX_VALUE ` ,可以理解为线程数是可以无限扩展的,可能会创建大量线程,从而导致 OOM。
499
- - ` DelayedWorkQueue ` (延迟阻塞队列):` ScheduledThreadPool ` 和 ` SingleThreadScheduledExecutor ` 。` DelayedWorkQueue ` 的内部元素并不是按照放入的时间排序,而是会按照延迟的时间长短对任务进行排序,内部采用的是“堆”的数据结构,可以保证每次出队的任务都是当前队列中执行时间最靠前的。` DelayedWorkQueue ` 添加元素满了之后会自动扩容原来容量的 1/2,即永远不会阻塞,最大扩容可达 ` Integer.MAX_VALUE ` ,所以最多只能创建核心线程数的线程。
509
+ - ` DelayedWorkQueue ` (延迟队列):` ScheduledThreadPool ` 和 ` SingleThreadScheduledExecutor ` 。` DelayedWorkQueue ` 的内部元素并不是按照放入的时间排序,而是会按照延迟的时间长短对任务进行排序,内部采用的是“堆”的数据结构,可以保证每次出队的任务都是当前队列中执行时间最靠前的。` DelayedWorkQueue ` 添加元素满了之后会自动扩容,增加原来容量的 50%,即永远不会阻塞,最大扩容可达 ` Integer.MAX_VALUE ` ,所以最多只能创建核心线程数的线程。
510
+ - ` ArrayBlockingQueue ` (有界阻塞队列):底层由数组实现,容量一旦创建,就不能修改。
500
511
501
512
### 线程池处理任务的流程了解吗?
502
513
0 commit comments