为什么要使用线程池?

1
避免因线程切换而造成的性能损耗

构造ThreadPoolExecutor线程池的参数

构造参数1
构造参数2
构造参数3
构造参数4

1
2
3
4
5
6
7
8
9
10
11
corePoolSize: 核心线程数
maximumPoolSize: 最大线程数
keepAliveTime: 线程空闲时间
unit: keepAliveTime参数单位
workQueue: 缓存线程任务阻塞队列
threadFactory: 指定创建线程的工厂
handler: 当提交任务数超过maximumPoolSize+workQueue之和时,任务会交给handler来处理,有4个取值:
1.new ThreadPoolExecutor.CallerRunsPolicy(): 拒绝任务的处理程序,它直接在execute方法的调用线程中运行拒绝任务
2.new ThreadPoolExecutor.AbortPolicy(): 抛出RejectedExecutionException拒绝任务的处理程序
3.new ThreadPoolExecutor.DiscardPolicy(): 拒绝任务的处理程序,静默丢弃被拒绝的任务
4.new ThreadPoolExecutor.DiscardOldestPolicy(): 拒绝任务的处理程序,丢弃最旧的未处理请求,然后重试execute

基本用法

1
2
3
4
1.定义Runnable或Callable类型的任务
2.创建ThreadPoolExecutor对象
3.将任务放入ThreadPoolExecutor对象中
4.任务运行结束后通过shutdown方法关闭ThreadPoolExecutor对象

代码展示

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
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;

public class ThreadLocalTest extends Thread {

private final String name;

public ThreadLocalTest(String name) {
this.name = name;
}

@Override
public void run() {

System.out.println("Thread: " + name + "执行");

try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("Thread: " + name + "结束");

}

public static void main(String[] args) {

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 4, 200, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<>(10));

for (int i = 0; i < 10; i++) threadPoolExecutor.execute(new ThreadLocalTest(String.valueOf(i)));

threadPoolExecutor.shutdown();

}
}

打印展示

ThreadPoolExecutor线程池执行器

ThreadPoolExecutor线程池工作方式

1
2
3
4
1.创建线程池后,线程会随着任务到来的到来而创建
2.线程池中的任务数超出corePoolSize,workQueue队列未满,就会将任务放入到workQueue队列中
3.线程池中的任务数超出corePoolSize,workQueue队列已满,且线程池中的任务数小于maximumPoolSize,会创建maximumPoolSize减corePoolSize再减workQueue个新线程来处理被添加的任务
4.workQueue队列若无界,任务会一直丢到队列中,会导致OutOfMemoryError异常

代码展示

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
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;

public class ThreadLocalTest implements Runnable {

@Override
public void run() {

}

public static void main(String[] args) {

/* 未超出核心线程数 */
extracted(4);

/* 超出核心线程数 */
extracted(8);

/* 超出缓存线程队列 */
extracted(12);

}

private static void extracted(int size) {

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 200,
TimeUnit.MICROSECONDS, new ArrayBlockingQueue<>(5));

for (int i = 0; i < size; i++) {

threadPoolExecutor.execute(new ThreadLocalTest());

System.out.println("线程池任务数量: " + threadPoolExecutor.getPoolSize() + " 队列任务数量: " +
threadPoolExecutor.getQueue().size() + " 已完成任务数量: " + threadPoolExecutor.getCompletedTaskCount());

}

System.out.println("-----分隔线-----");

threadPoolExecutor.shutdown();

}
}

打印展示

ThreadPoolExecutor线程池工作方式