为什么阿里巴巴规范里面不允许使用Executors去创建

先看下Executors能创建哪几种常用的线程池

newFixedThreadPool

1
2
3
4
5
6
7
8
9
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}

newSingleThreadExecutor

1
2
3
4
5
6
7
8
9
10
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}

public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}

newCachedThreadPool

1
2
3
4
5
6
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

newScheduledThreadPool

1
2
3
4
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}

当线程数量过多时,都会引起OOM

那么推荐使用自定义线程池

自定义线程池

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

public class CustomThreadPool {

private static final int CORE_POOL_SIZE = 10; // 核心线程数
private static final int MAX_POOL_SIZE = 100; // 最大线程数
private static final long KEEP_ALIVE_TIME = 60L; // 线程空闲超时时间
private static final int QUEUE_CAPACITY = 200; // 任务队列容量

public static void main(String[] args) {
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
CORE_POOL_SIZE, // 核心线程数
MAX_POOL_SIZE, // 最大线程数
KEEP_ALIVE_TIME, // 线程空闲超时时间
TimeUnit.SECONDS, // 时间单位
new ArrayBlockingQueue<>(QUEUE_CAPACITY), // 任务队列
new ThreadPoolExecutor.CallerRunsPolicy() // 线程池拒绝策略
);

// 提交任务
for (int i = 0; i < 10; i++) {
executor.execute(new Task(i));
}

// 关闭线程池
executor.shutdown();
}

private static class Task implements Runnable {
private final int taskId;

public Task(int taskId) {
this.taskId = taskId;
}

@Override
public void run() {
System.out.println("Task #" + taskId + " is running on thread " + Thread.currentThread().getName());
}
}
}

线程池拒绝策略有哪些

1
2
3
4
AbortPolicy: 直接抛出RejectedExecutionException异常,这是默认的拒绝策略。
CallerRunsPolicy: 使用调用者所在的线程来执行任务,即提交任务的线程执行该任务。
DiscardPolicy: 直接丢弃无法处理的任务,不做任何处理。
DiscardOldestPolicy: 丢弃最老的未处理任务,然后重新尝试添加该任务。

线程池执行流程

  1. 当有任务提交到线程池时,线程池会先检查当前线程池中的线程数是否达到了核心线程数,如果没有,则会创建新的线程来执行任务。如果已经达到了核心线程数,但是任务队列未满,则将任务添加到任务队列中等待执行。

  2. 当任务队列已满时,线程池会继续创建新的线程来执行任务,直到达到最大线程数为止。

  3. 当线程池中的线程数量已经达到了最大线程数,但是任务队列已满时,根据拒绝策略来处理新提交的任务。

  4. 当线程池中的某个线程执行完任务后,它会从任务队列中获取下一个任务来执行,直到线程池关闭或者线程池中的所有线程都处于空闲状态并且超过了keepAliveTime所设定的时间,这些线程才会被终止。

在上述执行流程中,线程池的核心作用是管理线程的数量以及任务队列的大小,从而有效地控制系统中的并发请求。