MST

星途 面试题库

面试题:Java可缓存线程池资源管理的性能优化

在高并发场景下,Java可缓存线程池可能会出现性能瓶颈,特别是在资源管理方面。请阐述你所知道的针对可缓存线程池资源管理的性能优化策略,包括但不限于线程创建与销毁的优化、任务调度优化等,并说明如何通过代码实现这些优化策略。
11.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

线程创建与销毁的优化

  1. 重用线程:可缓存线程池默认会在一定时间(60秒)内缓存空闲线程。为了减少线程创建与销毁开销,确保业务场景下线程的复用率足够高。
    • 代码实现:使用Executors.newCachedThreadPool()创建线程池时,系统会自动管理线程的缓存与复用。
    ExecutorService executorService = Executors.newCachedThreadPool();
    for (int i = 0; i < 10; i++) {
        executorService.submit(() -> {
            // 执行任务
            System.out.println(Thread.currentThread().getName() + " is running task");
        });
    }
    executorService.shutdown();
    
  2. 限制线程创建数量:虽然可缓存线程池理论上可创建无限线程,但在高并发场景可能导致资源耗尽。可以自定义线程池并设置最大线程数。
    • 代码实现
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
        0, // 核心线程数为0
        100, // 最大线程数为100
        60L, TimeUnit.SECONDS,
        new SynchronousQueue<>());
    for (int i = 0; i < 10; i++) {
        executor.submit(() -> {
            // 执行任务
            System.out.println(Thread.currentThread().getName() + " is running task");
        });
    }
    executor.shutdown();
    

任务调度优化

  1. 优先队列调度:对于有优先级的任务,可以使用PriorityBlockingQueue作为任务队列,让线程池按照任务优先级执行。
    • 代码实现
    class PriorityTask implements Runnable, Comparable<PriorityTask> {
        private int priority;
        private String taskName;
        public PriorityTask(int priority, String taskName) {
            this.priority = priority;
            this.taskName = taskName;
        }
        @Override
        public void run() {
            System.out.println(taskName + " with priority " + priority + " is running");
        }
        @Override
        public int compareTo(PriorityTask other) {
            return Integer.compare(this.priority, other.priority);
        }
    }
    PriorityBlockingQueue<Runnable> taskQueue = new PriorityBlockingQueue<>();
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
        0, 100, 60L, TimeUnit.SECONDS,
        taskQueue);
    executor.submit(new PriorityTask(3, "Task 3"));
    executor.submit(new PriorityTask(1, "Task 1"));
    executor.submit(new PriorityTask(2, "Task 2"));
    executor.shutdown();
    
  2. 分队列调度:根据任务类型将任务分配到不同队列,每个队列可配置不同的线程数处理。
    • 代码实现
    class Type1Task implements Runnable {
        @Override
        public void run() {
            System.out.println("Type 1 task is running");
        }
    }
    class Type2Task implements Runnable {
        @Override
        public void run() {
            System.out.println("Type 2 task is running");
        }
    }
    BlockingQueue<Runnable> type1Queue = new ArrayBlockingQueue<>(100);
    BlockingQueue<Runnable> type2Queue = new ArrayBlockingQueue<>(100);
    ThreadPoolExecutor type1Executor = new ThreadPoolExecutor(
        5, 10, 60L, TimeUnit.SECONDS, type1Queue);
    ThreadPoolExecutor type2Executor = new ThreadPoolExecutor(
        3, 5, 60L, TimeUnit.SECONDS, type2Queue);
    type1Executor.submit(new Type1Task());
    type2Executor.submit(new Type2Task());
    type1Executor.shutdown();
    type2Executor.shutdown();
    

其他优化策略

  1. 线程池监控与调整:使用ThreadPoolExecutor提供的监控方法,如getActiveCount()getTaskCount()等,实时了解线程池运行状态,动态调整线程池参数。
    • 代码实现
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
        0, 100, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
    for (int i = 0; i < 10; i++) {
        executor.submit(() -> {
            // 执行任务
            System.out.println(Thread.currentThread().getName() + " is running task");
        });
    }
    System.out.println("Active threads: " + executor.getActiveCount());
    System.out.println("Total tasks: " + executor.getTaskCount());
    executor.shutdown();
    
  2. 合理设置线程存活时间:可缓存线程池默认线程存活时间为60秒,可根据业务负载情况适当调整这个时间。如果任务执行频率高且持续时间短,可适当延长存活时间;如果任务执行频率低,可缩短存活时间以释放资源。
    • 代码实现
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
        0, 100, 30L, TimeUnit.SECONDS, new SynchronousQueue<>());
    // 执行任务
    executor.shutdown();