线程池
1、线程池的7个参数
corePoolSize
, 核心线程数,当新的任务到来时,如果当前核心线程的数量没有>
设置的值就新建一个线程执行该任务;否则,就将新任务放入工作队列/等待队列中maximumPoolSize
,线程池的最大线程数,当新任务到来时,如果当前线程数量 >= maximumPoolSize
,执行拒绝策略handler
;否则,- 将任务加入工作队列,
当前线程数量 == corePoolSize && workQueue 未满
- 或者新建核心线程执行,
当前线程数量 < corePoolSize
- 或者新建工作线程执行,
当前线程数量 == corePoolSize && workQueue 以满
- 将任务加入工作队列,
keepAliveTime
, 保活时间,一个线程空闲的最长时间,long型,单位由unit
决定。- 默认只会对非核心线程起作用,可以通过
threadPoolExecutor.allowCoreThreadTimeOut(true);
设置为对核心线程起作用,此时,必须满足keepAliveTime>0
,因为核心线程必须存活时间大于0;否则会抛出IllegalArgumentException("Core threads must have nonzero keep alive times");
异常
- 默认只会对非核心线程起作用,可以通过
unit
, 保活时间的单位,取值从TimeUnit
这个枚举类中取值workQueue
, 当新的任务到来时,如果,当前线程数量 == corePoolSize && workQueue 未满
,将任务加入工作队列threadFactory
, 线程工厂,可以使用自定义的线程工程,自定义线程名字的前缀,方便排查问题handler
, 拒绝策略,当当前的线程数量 == maximumPoolSize && workQueue 已满
,执行拒绝策略ThreadPoolExecutor.AbortPolicy
:丢弃任务并抛出RejectedExecutionException
异常。ThreadPoolExecutor.DiscardPolicy
:丢弃任务,但是不抛出异常。ThreadPoolExecutor.DiscardOldestPolicy
:丢弃队列最前面的任务,然后重新提交被拒绝的任务ThreadPoolExecutor.CallerRunsPolicy
:由调用线程(提交任务的线程)处理该任务
2、简单使用
package org.example;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import java.util.concurrent.*;
@Slf4j
public class ThreadPoolTest {
@Test
public void ThreadPoolCreateTest() {
// 线程池参数 初始化
int corePoolSize = 2;
int maximumPoolSize = 3;
long keepAliveTime = 0L;
TimeUnit unit = TimeUnit.MILLISECONDS;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(1);
ThreadFactory threadFactory = new CustomizableThreadFactory("GROUP");
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
// 创建线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
threadFactory,
handler
);
long taskCount = threadPoolExecutor.getTaskCount();
// threadPoolExecutor.allowCoreThreadTimeOut(true); // 要是用这个,必须同步把 keepAliveTime 设置为 > 0
log.info("taskCount : {}", taskCount);
// 新建task
Runnable Runnable = new Runnable() {
@Override
public void run() {
log.info("ThreadName : {}", Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
log.error("{}", e);
}
}
};
// 线程池调用
for (int i = 0; i < 10; i++) {
System.out.println(i);
threadPoolExecutor.execute(Runnable);
}
}
}
21:46:24.433 [main] INFO org.example.ThreadPoolTest - taskCount : 0
0
1
2
3
4
21:46:24.436 [GROUP1] INFO org.example.ThreadPoolTest - ThreadName : GROUP1 // i = 0
21:46:24.436 [GROUP2] INFO org.example.ThreadPoolTest - ThreadName : GROUP2 // i = 1
21:46:24.436 [GROUP3] INFO org.example.ThreadPoolTest - ThreadName : GROUP3 // i = 3
说明:
- 当想要创建第四个线程的时候,发生了异常 因为 maximumPoolSize=3
- 当 i=0和1的时候,创建的是核心线程,执行了任务,sleep
- 当i=2时,任务进入工作队列
- 当i=3时,任务被新建的工作线程执行
- 当i=4时,任务到来时,发现当前线程池的线程数==maximumPoolSize,并且工作队列已满,所以抛出异常