面试题答案
一键面试线程池资源隔离方案设计
- 按任务类型划分线程池:根据不同任务类型创建独立的线程池。例如,如果任务类型分为
TaskTypeA
、TaskTypeB
和TaskTypeC
,分别创建ThreadPoolA
、ThreadPoolB
和ThreadPoolC
。ExecutorService threadPoolA = Executors.newFixedThreadPool(5); ExecutorService threadPoolB = Executors.newFixedThreadPool(3); ExecutorService threadPoolC = Executors.newFixedThreadPool(4);
- 任务提交与执行:在任务产生时,根据任务类型将其提交到对应的线程池。
public void submitTask(Task task) { if (task instanceof TaskTypeA) { threadPoolA.submit(task::execute); } else if (task instanceof TaskTypeB) { threadPoolB.submit(task::execute); } else if (task instanceof TaskTypeC) { threadPoolC.submit(task::execute); } }
- 资源分配与限制:根据不同任务类型对资源的需求,合理设置每个线程池的核心线程数、最大线程数、队列容量等参数。例如,若
TaskTypeA
对资源需求较高,可以设置较大的核心线程数和最大线程数。ThreadPoolExecutor threadPoolExecutorA = new ThreadPoolExecutor( 5, // 核心线程数 10, // 最大线程数 10L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(20) // 队列容量 );
线程池参数动态优化
- 监控系统负载:使用
java.lang.management
包中的类来监控系统的负载情况,如ThreadMXBean
监控线程相关指标,OperatingSystemMXBean
监控系统资源使用情况。ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean(); long totalCpuTime = osBean.getProcessCpuTime(); int activeThreadCount = threadMXBean.getThreadCount();
- 动态调整线程池参数:根据监控到的负载情况,调整线程池的核心线程数、最大线程数和队列容量。例如,当系统负载较低且任务队列中有较多任务等待时,可以适当增加核心线程数。
public void adjustThreadPool(ThreadPoolExecutor executor, int loadFactor) { if (loadFactor < 50) { // 假设负载因子小于50表示负载较低 if (executor.getCorePoolSize() < executor.getMaximumPoolSize()) { executor.setCorePoolSize(executor.getCorePoolSize() + 1); } } else if (loadFactor > 80) { // 假设负载因子大于80表示负载较高 if (executor.getCorePoolSize() > 1) { executor.setCorePoolSize(executor.getCorePoolSize() - 1); } } }
- 定期评估与调整:通过定时任务(如
ScheduledExecutorService
)定期获取系统负载并调整线程池参数。ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate(() -> { int loadFactor = calculateLoadFactor(); // 自定义计算负载因子方法 adjustThreadPool(threadPoolExecutorA, loadFactor); adjustThreadPool(threadPoolExecutorB, loadFactor); adjustThreadPool(threadPoolExecutorC, loadFactor); }, 0, 1, TimeUnit.MINUTES);