面试题答案
一键面试性能瓶颈和资源管理问题分析
- 线程池饱和:当任务提交速度超过线程池处理能力,队列被填满后新任务会被拒绝,导致系统响应变慢甚至任务丢失。
- 内存泄漏:如果CompletableFuture对象没有正确释放,其内部引用的资源(如线程、任务等)无法被垃圾回收,可能导致内存泄漏。
- 上下文切换开销:过多线程竞争CPU资源,频繁上下文切换会降低系统性能。
- 资源浪费:线程池创建过多线程,但实际任务执行时间短,会造成线程资源浪费。
优化策略和解决方案
- 合理配置线程池参数
- 核心线程数:根据CPU核心数和任务类型确定,I/O密集型任务可适当增大核心线程数,CPU密集型任务接近CPU核心数。
- 最大线程数:防止线程无限增长,避免资源耗尽。
- 队列容量:根据任务处理速度和提交频率设置,避免队列过长导致内存占用过多。
- 存活时间:设置非核心线程存活时间,及时回收空闲线程。
- 任务调度策略调整
- 优先级队列:对任务设置优先级,优先处理重要任务。
- 分类调度:将不同类型任务分配到不同线程池处理,避免互相干扰。
- 资源回收机制设计
- 确保CompletableFuture对象在使用完毕后正确释放,避免强引用导致内存泄漏。
代码示例
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class CompletableFutureOptimization {
// 自定义线程池
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心线程数
10, // 最大线程数
10L, TimeUnit.SECONDS, // 存活时间
new ArrayBlockingQueue<>(100), // 队列容量
new ThreadFactory() {
private final AtomicInteger threadNumber = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "MyThread-" + threadNumber.getAndIncrement());
thread.setDaemon(false);
return thread;
}
},
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
public static void main(String[] args) {
for (int i = 0; i < 200; i++) {
CompletableFuture.supplyAsync(() -> {
// 模拟任务执行
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Task " + Thread.currentThread().getName() + " completed";
}, executor)
.thenAccept(System.out::println)
.exceptionally(e -> {
e.printStackTrace();
return null;
});
}
// 优雅关闭线程池
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
System.err.println("Pool did not terminate");
}
}
} catch (InterruptedException ie) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
上述代码展示了如何自定义线程池,并使用CompletableFuture结合该线程池执行异步任务,同时包含了线程池优雅关闭的操作。
伪代码示例
# 定义线程池参数
core_pool_size = 5
max_pool_size = 10
keep_alive_time = 10
queue_capacity = 100
# 创建线程池
executor = ThreadPoolExecutor(core_pool_size, max_pool_size, keep_alive_time, TimeUnit.SECONDS, ArrayBlockingQueue(queue_capacity))
for i in range(200):
future = CompletableFuture.supplyAsync(lambda: {
# 模拟任务执行
sleep(0.1)
return "Task " + current_thread().name + " completed"
}, executor)
future.then_accept(print)
future.exceptionally(lambda e: {
print(e)
return None
})
# 优雅关闭线程池
executor.shutdown()
try:
if not executor.awaitTermination(60, TimeUnit.SECONDS):
executor.shutdownNow()
if not executor.awaitTermination(60, TimeUnit.SECONDS):
print("Pool did not terminate")
except InterruptedException:
executor.shutdownNow()
current_thread().interrupt()
伪代码部分以Python风格展示了类似的逻辑,主要体现任务提交到线程池以及线程池关闭的过程。