小渣的Java实习日记:线程池的使用与优化
场景引入
今天,小渣和mentor聊起了多线程编程。mentor说:“小渣,上次我们讨论了多线程的基础知识,今天我们来聊聊线程池的使用和优化。线程池是Java并发编程中非常重要的工具,合理使用可以显著提升性能。”
小渣点点头:“好的,我之前也听说过线程池,但具体怎么用还不太清楚。”
线程池的基本概念
mentor解释道:“线程池的核心思想是复用线程,避免频繁创建和销毁线程带来的性能开销。Java提供了ExecutorService接口和ThreadPoolExecutor类来实现线程池。”
线程池的创建
以下是一个简单的线程池创建示例:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo {
public static void main(String[] args) {
// 创建一个固定大小的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
// 提交任务
for (int i = 0; i < 10; i++) {
executor.submit(() -> {
System.out.println("任务执行线程:" + Thread.currentThread().getName());
});
}
// 关闭线程池
executor.shutdown();
}
}
解释:
Executors.newFixedThreadPool(5)创建了一个固定大小为5的线程池。executor.submit()提交任务到线程池。executor.shutdown()关闭线程池,不再接受新任务。
线程池的优化
mentor接着说:“线程池虽然好用,但如果不合理配置,可能会导致性能问题。比如,任务队列过长、线程数过多或过少都会影响性能。”
自定义线程池
更推荐的方式是直接使用ThreadPoolExecutor,可以灵活配置参数:
import java.util.concurrent.*;
public class CustomThreadPoolDemo {
public static void main(String[] args) {
// 自定义线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // 核心线程数
5, // 最大线程数
60, // 空闲线程存活时间
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<>(10), // 任务队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);
// 提交任务
for (int i = 0; i < 15; i++) {
try {
executor.submit(() -> {
System.out.println("任务执行线程:" + Thread.currentThread().getName());
});
} catch (RejectedExecutionException e) {
System.out.println("任务被拒绝:" + e.getMessage());
}
}
// 关闭线程池
executor.shutdown();
}
}
解释:
- 核心线程数、最大线程数、任务队列大小等参数可以根据实际需求调整。
- 拒绝策略
AbortPolicy会在任务队列满时抛出异常,其他策略还有CallerRunsPolicy、DiscardPolicy等。
常见问题与解决方案
-
线程池大小设置不合理:
- CPU密集型任务:线程数建议设置为CPU核心数+1。
- IO密集型任务:线程数可以适当增加,比如2*CPU核心数。
-
任务队列过长:
- 使用有界队列(如
LinkedBlockingQueue)避免内存溢出。
- 使用有界队列(如
-
线程泄漏:
- 确保任务不会因为异常导致线程无法释放。
总结
通过今天的学习,小渣对线程池的使用和优化有了更深入的理解。线程池是Java并发编程中的重要工具,合理配置可以显著提升性能。在实际开发中,需要根据任务类型和系统资源灵活调整参数。
小渣的收获:
- 学会了如何创建和配置线程池。
- 了解了线程池的常见问题及优化方法。
- 通过代码示例加深了对线程池的理解。
431

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



