【线程与线程池】线程数设置
- [0. 全局使用一个线程池](#0. 全局使用一个线程池)
- [1. 按照任务类型对线程池进行分类](#1. 按照任务类型对线程池进行分类)
-
- [1.1 Netty的IO处理任务,就是典型的IO密集型任务](#1.1 Netty的IO处理任务,就是典型的IO密集型任务)
- [2. 混合型任务创建线程池时,如何确定线程数](#2. 混合型任务创建线程池时,如何确定线程数)
0. 全局使用一个线程池
java
import java.util.concurrent.*;
public class GlobalThreadPool {
// 单例线程池
private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
10, // 核心线程数
50, // 最大线程数
60L, TimeUnit.SECONDS, // 空闲线程最大存活时间
new LinkedBlockingQueue<>(1000), // 工作队列
new ThreadFactory() {
private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
private int counter = 0;
@Override
public Thread newThread(Runnable r) {
Thread thread = defaultFactory.newThread(r);
thread.setName("global-thread-" + counter++);
return thread;
}
},
new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);
private GlobalThreadPool() {
// 私有构造防止实例化
}
public static ThreadPoolExecutor getExecutor() {
return EXECUTOR;
}
}
业务中使用
java
import java.util.concurrent.Future;
public class Demo {
public void runTask() {
Runnable task = () -> {
System.out.println("执行任务:" + Thread.currentThread().getName());
};
// 提交任务
GlobalThreadPool.getExecutor().execute(task);
}
}
也可以使用 submit() 获取 Future 对象:
java
Future<String> future = GlobalThreadPool.getExecutor().submit(() -> {
// 业务逻辑
return "result";
});
优雅关闭线程池(如在应用退出时)
java
public class ShutdownHook {
public static void register() {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("关闭全局线程池...");
GlobalThreadPool.getExecutor().shutdown();
try {
if (!GlobalThreadPool.getExecutor().awaitTermination(60, TimeUnit.SECONDS)) {
GlobalThreadPool.getExecutor().shutdownNow();
}
} catch (InterruptedException e) {
GlobalThreadPool.getExecutor().shutdownNow();
}
}));
}
}
在 Spring Boot 中可以在 @PostConstruct 中调用注册:
@Component
public class AppInitializer {
@PostConstruct
public void init() {
ShutdownHook.register();
}
}
另一种方法
java
在 Spring Boot 中,更建议使用 Spring 的 @Bean + 注入方式统一线程池,例如:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PreDestroy;
import java.util.concurrent.*;
@Configuration
public class ThreadPoolConfig {
@Value("${threadpool.corePoolSize:10}")
private int corePoolSize;
@Value("${threadpool.maxPoolSize:50}")
private int maxPoolSize;
@Value("${threadpool.queueCapacity:1000}")
private int queueCapacity;
@Value("${threadpool.keepAliveSeconds:60}")
private long keepAliveSeconds;
@Value("${threadpool.threadNamePrefix:global-pool}")
private String threadNamePrefix;
@Value("${threadpool.rejectedPolicy:CallerRunsPolicy}")
private String rejectedPolicy;
private ThreadPoolExecutor executor;
@Bean(name = "globalExecutor", destroyMethod = "") // 禁用 Spring 自动销毁,手动控制
public Executor globalExecutor() {
executor = new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveSeconds, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(queueCapacity),
new CustomThreadFactory(threadNamePrefix),
getRejectedExecutionHandler()
);
return executor;
}
@PreDestroy
public void shutdown() {
if (executor != null) {
System.out.println("[ThreadPoolConfig] 正在关闭线程池...");
executor.shutdown();
try {
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
System.out.println("[ThreadPoolConfig] 超时未关闭,强制关闭线程池");
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
System.out.println("[ThreadPoolConfig] 线程池关闭被中断,已强制关闭");
}
System.out.println("[ThreadPoolConfig] 线程池已成功关闭");
}
}
private RejectedExecutionHandler getRejectedExecutionHandler() {
switch (rejectedPolicy) {
case "AbortPolicy":
return new ThreadPoolExecutor.AbortPolicy();
case "DiscardPolicy":
return new ThreadPoolExecutor.DiscardPolicy();
case "DiscardOldestPolicy":
return new ThreadPoolExecutor.DiscardOldestPolicy();
case "CallerRunsPolicy":
default:
return new ThreadPoolExecutor.CallerRunsPolicy();
}
}
private static class CustomThreadFactory implements ThreadFactory {
private final String prefix;
private final ThreadGroup group;
private int count = 1;
CustomThreadFactory(String prefix) {
this.prefix = prefix;
this.group = Thread.currentThread().getThreadGroup();
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, prefix + "-thread-" + count++);
t.setDaemon(false);
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
}
使用方式:
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.concurrent.Executor;
@Service
public class TaskService {
private final Executor globalExecutor;
@Autowired
public TaskService(@Qualifier("globalExecutor") Executor globalExecutor) {
this.globalExecutor = globalExecutor;
}
public void submitTasks() {
for (int i = 1; i <= 5; i++) {
int taskId = i;
globalExecutor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 正在执行任务: " + taskId);
try {
Thread.sleep(2000); // 模拟任务执行耗时
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + " 完成任务: " + taskId);
});
}
}
}
@Qualifier("globalExecutor") 的作用是指定注入哪个具体的 Bean。是否必须加它,取决于你项目中是否存在多个同类型的 Bean。
启动入口调用(例如在 Spring Boot 主类或测试里)
java
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class Runner implements CommandLineRunner {
private final TaskService taskService;
public Runner(TaskService taskService) {
this.taskService = taskService;
}
@Override
public void run(String... args) throws Exception {
System.out.println("提交任务到全局线程池...");
taskService.submitTasks();
}
}
1. 按照任务类型对线程池进行分类
1.1 Netty的IO处理任务,就是典型的IO密集型任务
2. 混合型任务创建线程池时,如何确定线程数

P10