面试题答案
一键面试线程池性能优化
- 合理配置线程池参数
- 核心线程数(corePoolSize):根据任务类型和系统资源来设置。对于CPU密集型任务,一般设置为
CPU核心数 + 1
。例如,系统有4个CPU核心,对于CPU密集型任务,核心线程数可以设置为5。
int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
- 最大线程数(maximumPoolSize):如果任务队列可能会被大量任务填满,需要设置一个合理的最大值。对于I/O密集型任务,最大线程数可以设置得相对较大,比如
CPU核心数 * 2
。
int maximumPoolSize = Runtime.getRuntime().availableProcessors() * 2;
- 队列容量(workQueue):选择合适的队列类型和容量。对于有界队列,如
ArrayBlockingQueue
,要根据任务的预估数量设置合理容量。
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(100);
- 核心线程数(corePoolSize):根据任务类型和系统资源来设置。对于CPU密集型任务,一般设置为
- 优化任务执行逻辑
- 减少任务内部的锁竞争:避免在任务执行过程中频繁使用锁,尽量采用无锁数据结构或线程安全的设计模式。例如,使用
ConcurrentHashMap
替代HashMap
来减少锁竞争。
Map<String, Integer> map = new ConcurrentHashMap<>();
- 避免不必要的I/O操作:如果任务涉及I/O操作,尽量批量处理或者采用异步I/O。例如,在文件读写时,使用
BufferedReader
和BufferedWriter
进行批量读写。
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt")); BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) { String line; while ((line = reader.readLine()) != null) { // 处理逻辑 writer.write(line); writer.newLine(); } } catch (IOException e) { e.printStackTrace(); }
- 减少任务内部的锁竞争:避免在任务执行过程中频繁使用锁,尽量采用无锁数据结构或线程安全的设计模式。例如,使用
资源隔离策略
- 线程池隔离
- 按任务类型划分线程池:例如,在一个电商系统中,将订单处理任务和商品查询任务分别放入不同的线程池。
// 订单处理线程池 ExecutorService orderThreadPool = new ThreadPoolExecutor( 5, 10, 10L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100) ); // 商品查询线程池 ExecutorService productQueryThreadPool = new ThreadPoolExecutor( 3, 6, 10L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(50) );
- 任务提交:
// 提交订单处理任务 orderThreadPool.submit(() -> { // 订单处理逻辑 }); // 提交商品查询任务 productQueryThreadPool.submit(() -> { // 商品查询逻辑 });
- 信号量隔离
- 使用Semaphore:例如,在一个微服务调用场景中,限制对某个外部接口的并发调用数。
Semaphore semaphore = new Semaphore(5); // 允许同时5个线程调用 try { semaphore.acquire(); // 调用外部接口逻辑 } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); }