06-40行代码搞透线程池

1. 线程测试Demo

结论在注释中,建议自己跑一跑。

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
* 测试线程池
*
* @author Jerry(小姜)
* @date 2021-10-17 17:50
*/
public class ThreadPoolExecutorTest {
/**
* 5 ≈ 541ms (余数 41ms 为代码执行时间)
* 10 ≈ 555ms
* 11 ≈ 1062ms
* 20 ≈ 1053ms
* 30 ≈ 1544ms
* 40 ≈ 2061ms (40-30=10, 40 = 10+10+10+10 = 500+500+500+500 ≈ 2000ms)
* 41 ≈ 2050ms (41-30=11, 41 = 11+11+11+8 = 500+500+500+500 ≈ 1500ms)
* 45 ≈ 1564ms (45-30=15, 45 = 15+15+15 = 500+500+500 ≈ 1500ms)
* 50 ≈ 1546ms (50-30=20, 50 = 20+20+10 = 500+500+500 ≈ 1500ms)
* 51 ≈ 超出的任务会被丢弃并抛出 RejectedExecutionException
* 44 ≈ ???
* 结论: 每组执行时间就等于单个任务执行时间,demo 中为 500ms
* 1. 当任务数 <= 核心线程数时,线程池中工作线程数 = 任务数
* 2. 当核心线程数 + 队列容量 < 任务数 <= 最大线程数 + 队列容量时,工作线程数 = 任务数 - 队列容量
* 因此当 44 个线程的时候,工作线程数=44-30=14,线程工作批次为 44=14+14+14+2=500+500+500+500≈2000ms
*/
private static final int taskCount = 5;//任务数

public static void main(String[] args) throws InterruptedException {
AtomicInteger integer = new AtomicInteger();
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10,//核心线程数
20,//最大线程数
5,//非核心回收超时时间
TimeUnit.SECONDS,//超时时间单位
new ArrayBlockingQueue<>(30)); //任务队列
System.out.println("总任务数:" + taskCount);
long start = System.currentTimeMillis();
//模拟任务提交
for (int i = 0; i < taskCount; i++) {
Thread thread = new Thread(() -> {
try {
Thread.sleep(500);//模拟执行耗时
System.out.println("已执行" + integer.addAndGet(1) + "个任务");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
try {
//注意这里我try起来了,默认拒绝策略会报错
executor.execute(thread);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
long end = 0;
while (executor.getCompletedTaskCount() < taskCount) {
end = System.currentTimeMillis();
}
System.out.println("任务总耗时:" + (end - start));
}
}

2. 结论

每组执行时间就等于单个任务执行时间(demo 中为 500ms)

  1. 当任务数 <= 核心线程数时,线程池中工作线程数 = 任务数

  2. 当核心线程数 + 队列容量 < 任务数 <= 最大线程数 + 队列容量时,工作线程数 = 任务数 - 队列容量

因此demo中当 44 个线程的时候,工作线程数=44-30=14,

线程工作批次为 44 = 14+14+14+2 = 500+500+500+500 ≈ 2000ms。


06-40行代码搞透线程池
https://janycode.github.io/2021/12/30/02_编程语言/01_Java/01_JavaSE/05_并发和锁/06-40行代码搞透线程池/
作者
Jerry(姜源)
发布于
2021年12月30日
许可协议