目录
线程池的作用:
线程池可以重复利用已创建的线程,来降低线程创建和销毁带来的开销;同时也可以使任务到达时就可以立刻执行,响应速度快;线程池还可以对创建的线程进行统一分配,调度和监控。
线程池的七大参数:
int corePoolSize;//核心线程数
int maxPoolSize;//最大线程数
long keepAliveTime;//核心线程空闲时间
TimeUnit timeUnit;//时间单位
BlockingQueue<Runnable> workQueue;//工作队列
ThreadFactory threadFactory;//线程工厂
RejectedExecutionHandler handler;//拒绝策略
执行流程:
拒绝策略:
CallerRunsPolicy()让调用者线程来执行被拒绝的任务
DiscardPolicy();抛弃被拒绝的任务
DiscardOldestPolicy();丢弃任务队列中最老的任务,然后尝试重新提交新任务
AbortPolicy();直接抛出异常
关闭线程池
shutdown() 方法会启动一个有序的关闭过程,执行中的任务会继续执行,但是不会再接受新的任务。线程池会等待所有正在执行的任务(包括核心线程和非核心线程执行的任务)完成后再关闭。核心线程和非核心线程在任务执行完毕后会被释放。
shutdownNow() 方法会尝试停止所有正在执行的活动任务,暂停处理等待中的任务,并返回等待执行的任务列表。它会尝试中断所有线程,包括核心线程和非核心线程。不过,线程是否能被中断取决于线程正在执行的任务是否响应中断。
下面是一个简易的线程池实现:
package ThreadPool;
import java.util.concurrent.*;
/**
* @author 小浣浣
* @verson 1.0
* @time 2025/5/10 23:43
*/
public class ThreadPoolTest {
private int corePoolSize = 2;// 核心线程数
private int maxPoolSize = 3;// 最大线程数
private long keepAliveTime = 60;// 线程空闲时间
private TimeUnit timeUnit = TimeUnit.SECONDS;//时间单位
private BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(3);// 工作队列
private ThreadFactory threadFactory = Executors.defaultThreadFactory();// 线程工厂
private RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();// 拒绝策略
private ThreadPoolExecutor executor;
/**
* 构造函数,初始化线程池
* 设置核心线程数、最大线程数、线程空闲时间、工作队列、线程工厂和拒绝策略
* 并将非核心线程的空闲时间设置为 60 秒
*/
public ThreadPoolTest() {
executor = new ThreadPoolExecutor(
corePoolSize, maxPoolSize, keepAliveTime,
timeUnit, workQueue, threadFactory, handler
);
// 非核心线程设置空闲时间为 60 秒
executor.setKeepAliveTime(60, TimeUnit.SECONDS);
}
/**
* 提交一个任务到线程池执行
* @param task 要执行的任务,实现了 Runnable 接口
*/
public void submitTask(Runnable task) {
executor.execute(task);
}
/**
* 优雅地关闭线程池,不再接受新任务,但会继续执行已提交的任务
*/
public void shutdown() {
executor.shutdown();
}
/**
* 立即关闭线程池,尝试停止所有正在执行的任务,并返回等待执行的任务列表
*/
public void shutdownNow() {
executor.shutdownNow();
}
/**
* 阻塞当前线程,等待线程池在指定时间内关闭
* @param timeout 等待的最长时间
* @param unit 时间单位
* @return 如果线程池在指定时间内关闭返回 true,否则返回 false
* @throws InterruptedException 如果在等待过程中当前线程被中断
*/
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return executor.awaitTermination(timeout, unit);
}
/**
* 优雅地关闭线程池,先调用 shutdown() 方法,若在 60 秒内未关闭,则调用 shutdownNow() 方法
*/
public void gracefulShutdown() {
this.shutdown();
try {
if (!this.awaitTermination(60, TimeUnit.SECONDS)) {
this.shutdownNow();
}
} catch (InterruptedException e) {
this.shutdownNow();
Thread.currentThread().interrupt();
}
}
/**
* 程序入口方法,创建线程池实例,提交 8 个任务到线程池,然后优雅地关闭线程池
*/
public static void main(String[] args) {
ThreadPoolTest threadPoolManager = new ThreadPoolTest();
// 提交一些任务到线程池
for (int i = 0; i < 8; i++) {
final int taskId = i;
threadPoolManager.submitTask(() -> {
System.out.println("正在执行任务: " + taskId + ",线程: " + Thread.currentThread().getName());
try {
// 模拟任务执行时间
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
threadPoolManager.gracefulShutdown();
}
}
执行结果==》拒绝策略:让调用者线程来执行被拒绝的任务
执行结果==》拒绝策略:抛弃被拒绝的任务
执行结果==》拒绝策略:丢弃任务队列中最老的任务,然后尝试重新提交新任务
执行结果==》拒绝策略:直接抛出异常