特性 | 多线程(手动创建) | 线程池(Executor框架) |
---|---|---|
线程创建 | 直接new Thread() ,每次创建新线程 |
预先创建线程池,复用已有线程 |
资源消耗 | 频繁创建/销毁线程,资源开销大 | 线程复用,减少系统开销 |
任务调度 | 手动管理线程启动和销毁 | 自动调度任务,支持队列、优先级等策略 |
资源控制 | 难以限制并发线程数量,易导致资源耗尽 | 可配置核心线程数、最大线程数、队列容量等 |
异常处理 | 需手动处理线程异常 | 可通过Future 或回调机制统一处理异常 |
适用场景 | 简单场景或少量并发任务 | 高并发、短任务、资源受限环境 |
// 手动多线程(不推荐!)
public class ManualThreadController {
@PostMapping("/upload")
public ResponseEntity handleFileUpload(@RequestParam("file") MultipartFile file) {
new Thread(() -> {
// 异步处理文件(无资源控制,可能引发线程爆炸)
processFile(file);
}).start();
return ResponseEntity.ok("Upload started");
}
}
// 使用线程池(推荐!)
@Configuration
public class ThreadPoolConfig {
@Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 核心线程数
executor.setMaxPoolSize(10); // 最大线程数
executor.setQueueCapacity(100); // 任务队列容量
executor.initialize();
return executor;
}
}
@RestController
public class AsyncController {
@Autowired
private Executor asyncExecutor;
@PostMapping("/upload")
public ResponseEntity handleFileUpload(@RequestParam("file") MultipartFile file) {
asyncExecutor.execute(() -> {
// 异步处理文件(受线程池资源控制)
processFile(file);
});
return ResponseEntity.ok("Upload started");
}
}
// 手动多线程(风险高)
public class ManualBatchProcessor {
public void processBatch(List dataList) {
for (Data data : dataList) {
new Thread(() -> processData(data)).start(); // 可能创建过多线程
}
}
}
// 使用线程池(安全高效)
public class PooledBatchProcessor {
private final ExecutorService pool = Executors.newFixedThreadPool(8);
public void processBatch(List dataList) {
List> futures = new ArrayList<>();
for (Data data : dataList) {
futures.add(pool.submit(() -> processData(data)));
}
// 等待所有任务完成
futures.forEach(future -> {
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
});
}
}
// 手动多线程(复杂且不可靠)
public class ManualScheduler {
public void scheduleTask(Runnable task, long delay) {
new Thread(() -> {
try {
Thread.sleep(delay);
task.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
// 使用线程池(简洁高效)
public class ScheduledExecutorDemo {
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(4);
public void scheduleTask(Runnable task, long delay) {
scheduler.schedule(task, delay, TimeUnit.MILLISECONDS);
}
}
ThreadPoolExecutor pool = new ThreadPoolExecutor(
CorePoolSize(5); // 核心线程数(常驻线程)
MaxPoolSize(10); // 最大线程数(临时线程上限)
QueueCapacity(100); // 任务队列容量
60, // 空闲线程存活时间(秒)
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), // 任务队列
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
最大线程数
)。@Async("customExecutor") // 指定线程池
public void asyncTask() { /* ... */ }
@Resource
private ManagedExecutorService executor; // 容器管理的线程池
SynchronousQueue
:直接传递任务(无缓冲)LinkedBlockingQueue
:无界队列(需防OOM)决策因素 | 选择多线程 | 选择线程池 |
---|---|---|
任务数量 | 少量(<10) | 大量(>10) |
任务执行时间 | 长任务(如文件下载) | 短任务(如HTTP请求) |
资源控制需求 | 无明确限制 | 需限制并发数、内存占用等 |
异常处理复杂度 | 需要自行处理 | 可通过Future 统一管理 |
项目维护性 | 低(代码分散) | 高(集中管理) |
--------分界线------------------------------------------------------------------------------------------------------
// 使用固定大小线程池的批量处理器
public class PooledBatchProcessor {
// 创建固定大小为8的线程池(根据硬件资源调整)
private final ExecutorService pool = Executors.newFixedThreadPool(8);
/**
* 批量处理方法(存在潜在问题)
* @param dataList 需要处理的数据列表
*/
public void processBatch(List dataList) {
// 存储异步任务结果的Future集合
List> futures = new ArrayList<>();
// 为每个数据项提交处理任务
for (Data data : dataList) {
// 提交任务到线程池,返回Future对象
futures.add(pool.submit(() -> processData(data)));
}
// 等待所有任务完成(潜在问题:顺序等待、异常处理不完善)
futures.forEach(future -> {
try {
// 阻塞获取结果(没有超时控制)
future.get();
} catch (InterruptedException | ExecutionException e) {
// 简单打印异常(应该更妥善处理)
e.printStackTrace();
}
});
}
}
没有关闭线程池的机制,可能导致资源泄漏
仅打印异常,未向上传递或统一处理
某个任务失败会导致后续future.get()立即终止吗?
逐个提交任务效率较低
没有超时控制可能导致永久阻塞
线程池参数硬编码
无法处理任务结果返回值
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
// 实现AutoCloseable确保资源释放
public class ImprovedBatchProcessor implements AutoCloseable {
// 可配置的线程池
private final ExecutorService pool;
// 构造函数支持自定义线程池
public ImprovedBatchProcessor(int poolSize) {
this.pool = Executors.newFixedThreadPool(poolSize);
}
/**
* 改进的批量处理方法
* @param dataList 待处理数据
* @param timeout 超时时间
* @param unit 时间单位
* @throws BatchProcessingException 自定义异常
*/
public void processBatch(List dataList, long timeout, TimeUnit unit)
throws BatchProcessingException {
// 使用CompletableFuture增强处理能力
List> futures = dataList.stream()
.map(data -> CompletableFuture.runAsync(() -> processData(data), pool))
.collect(Collectors.toList());
try {
// 统一等待所有任务完成(带超时控制)
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.get(timeout, unit);
} catch (TimeoutException e) {
throw new BatchProcessingException("Processing timed out", e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new BatchProcessingException("Processing interrupted", e);
} catch (ExecutionException e) {
throw new BatchProcessingException("Execution failed", e.getCause());
}
// 检查各个任务结果
checkForExceptions(futures);
}
private void checkForExceptions(List> futures)
throws BatchProcessingException {
// 收集所有异常信息
List exceptions = futures.stream()
.filter(CompletableFuture::isCompletedExceptionally)
.map(f -> {
try {
f.get();
return null;
} catch (InterruptedException | ExecutionException e) {
return e.getCause();
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (!exceptions.isEmpty()) {
BatchProcessingException batchException = new BatchProcessingException(
"Batch processing completed with " + exceptions.size() + " errors");
exceptions.forEach(batchException::addSuppressed);
throw batchException;
}
}
@Override
public void close() {
// 优雅关闭线程池
pool.shutdown();
try {
if (!pool.awaitTermination(5, TimeUnit.SECONDS)) {
pool.shutdownNow();
}
} catch (InterruptedException e) {
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
// 示例处理方法(需线程安全)
private void processData(Data data) {
// 实现具体业务逻辑
// 注意:需要保证线程安全
}
// 自定义异常类
public static class BatchProcessingException extends Exception {
public BatchProcessingException(String message, Throwable cause) {
super(message, cause);
}
public BatchProcessingException(String message) {
super(message);
}
}
}
场景:电商订单批量处理
public class OrderProcessingSystem {
public static void main(String[] args) {
// 从数据库获取待处理订单(示例)
List orders = loadPendingOrders(1000);
try (ImprovedBatchProcessor processor = new ImprovedBatchProcessor(16)) {
// 处理批量订单(设置5分钟超时)
processor.processBatch(orders, 5, TimeUnit.MINUTES);
System.out.println("Batch processing completed successfully");
} catch (ImprovedBatchProcessor.BatchProcessingException e) {
// 处理批量异常
System.err.println("Batch processing failed: " + e.getMessage());
e.getSuppressed().forEach(t ->
System.err.println("Suppressed error: " + t.getMessage()));
}
}
private static List loadPendingOrders(int count) {
// 实现订单加载逻辑
return new ArrayList<>();
}
}
class Order implements Data {
// 订单数据结构
}
CPU密集型任务:线程数 = CPU核心数 + 1
I/O密集型任务:线程数 = CPU核心数 * 2
使用ThreadPoolExecutor自定义参数(如队列类型、拒绝策略)
记录完整错误日志
实现重试机制(对失败任务)
使用断路器模式防止雪崩效应
使用批量提交(如每100条数据一个任务)
添加监控指标(任务队列大小、活跃线程数等)
考虑使用ForkJoinPool处理分治任务
始终使用try-with-resources确保关闭
配置合理的线程存活时间
添加日志记录点(任务开始/结束)
集成指标监控(Prometheus Metrics)
添加追踪标识(TraceID用于分布式追踪)
改进后的方案提供了更好的异常处理、资源管理和可配置性,适用于需要高吞吐量批量处理的场景,如:
金融交易批量处理
日志分析任务
大规模数据ETL
物联网设备数据处理
图片/视频批量处理
(望各位潘安、各位子健/各位彦祖、于晏不吝赐教!多多指正!)