一、Java 原生线程池(java.util.concurrent)
1.1 创建线程池(推荐使用 ThreadPoolExecutor)
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心线程数 corePoolSize
10, // 最大线程数 maximumPoolSize
60L, // 空闲线程存活时间 keepAliveTime
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<>(100), // 队列(有界队列防止 OOM)
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);
如果 线程数已经达到最大值,并且 队列也满了,线程池就没有能力再接新任务了。
这时必须要做一个选择 —— 这就是 拒绝策略。
📌 常见 拒绝策略:
AbortPolicy:抛异常(默认)。CallerRunsPolicy:由调用者线程执行任务。DiscardPolicy:直接丢弃任务。DiscardOldestPolicy:丢弃最旧任务,执行当前任务。
1.2 使用线程池
executor.execute(() -> System.out.println("执行任务1"));
Future<String> future = executor.submit(() -> "任务结果");
System.out.println(future.get()); // 阻塞等待结果
executor.shutdown(); // 关闭线程池
1.3 Executors 工厂方法(不推荐生产使用)
Executors.newFixedThreadPool(5); // 固定大小线程池
Executors.newCachedThreadPool(); // 缓存线程池,按需创建
Executors.newSingleThreadExecutor(); // 单线程
Executors.newScheduledThreadPool(5); // 定时/周期任务
👉 问题:这些方法的队列可能是 无界的,容易导致 OOM,所以阿里规范建议直接用 ThreadPoolExecutor。
二、Spring 线程池(推荐在企业项目中用)
Spring 对线程池做了封装,常用 ThreadPoolTaskExecutor(基于 Java ThreadPoolExecutor)。
2.1 配置线程池(Java Config 方式)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
public class ThreadPoolConfig {
@Bean("myExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 核心线程数
executor.setMaxPoolSize(10); // 最大线程数
executor.setQueueCapacity(100); // 队列容量
executor.setKeepAliveSeconds(60); // 空闲线程存活时间
executor.setThreadNamePrefix("my-thread-"); // 线程名前缀
executor.setRejectedExecutionHandler(new java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize(); // 初始化
return executor;
}
}
2.2 使用线程池
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Async("myExecutor") // 指定使用哪个线程池
public void asyncTask() {
System.out.println("执行异步任务:" + Thread.currentThread().getName());
}
}
⚡ 记得在启动类开启异步支持:
@EnableAsync
@SpringBootApplication
public class MyApplication { }
2.3 Spring Boot 配置文件方式(更简洁)
application.yml
spring:
task:
execution:
pool:
core-size: 5
max-size: 10
queue-capacity: 100
keep-alive: 60s
thread-name-prefix: my-thread-
使用时同样写 @Async 注解即可。
三、异步编程
CompletableFuture 是Futrue 的增强版,不阻塞线程,一般搭配线程池使用,执行异步任务。
Future 工作流程
主线程 ── submit(task) ──► 线程池执行task
主线程 ── get() ──(阻塞等待)────────────┐
│ 任务完成/异常
主线程 ◄────────────── 返回结果/抛异常 ─┘
CompletableFuture 工作流程
主线程 ── supplyAsync(task) ─► 线程池执行task
主线程 ── thenApply(...) / thenAccept(...)/whenComplete(...) // 只是注册回调,立刻返回
(稍后某时)
线程池工作线程:task完成 → 将“完成信号”分派给已注册的回调
异步执行任务,无线程
// thenApply: 有入参有返回(T -> R)
CompletableFuture<Integer> cf =
CompletableFuture.supplyAsync(() -> 21)
.thenApply(x -> x * 2); // -> 42
指定线程池
// 指定线程池
ExecutorService pool = Executors.newFixedThreadPool(8);
CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> "hi", pool);
2109

被折叠的 条评论
为什么被折叠?



