MST
星途 面试题库

面试题:自定义Java线程池实现及性能优化

假设你需要自定义一个线程池,以满足特定的高并发业务需求,要求线程池能够根据任务的优先级来优先执行高优先级任务。请详细说明你的设计思路,包括如何实现任务优先级管理,如何对线程池进行性能优化以避免线程饥饿和锁竞争等问题。
25.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 任务优先级管理
    • 定义一个实现 Comparable 接口的任务类,例如 PriorityTask,其中包含任务优先级字段。Comparable 接口的 compareTo 方法用于比较任务优先级,使得高优先级任务排在队列前面。
    • 使用 PriorityQueue 作为线程池的任务队列,PriorityQueue 会根据任务的优先级自动排序,保证高优先级任务在队列头部,优先被线程获取执行。
  2. 线程池性能优化 - 避免线程饥饿
    • 采用公平调度策略。可以通过使用 ReentrantLock 的公平锁模式,当任务被提交到线程池时,公平锁会按照任务提交的顺序依次分配给线程执行,避免高优先级任务持续占用资源导致低优先级任务长时间得不到执行。
    • 设置合理的线程存活时间。对于核心线程,可以设置为长期存活,保证系统一直有一定数量的线程处理任务;对于非核心线程,设置适当的存活时间,当任务队列空闲时,非核心线程能够及时释放资源,避免资源浪费,同时又能在任务量增加时快速创建线程处理任务,减少任务等待时间。
  3. 线程池性能优化 - 避免锁竞争
    • 减少锁的粒度。例如,对于任务队列的操作,使用 ConcurrentLinkedQueue 这种无锁队列来替代传统的加锁队列,ConcurrentLinkedQueue 通过无锁算法实现线程安全的队列操作,减少锁竞争带来的性能开销。
    • 采用分段锁。如果任务队列无法避免使用锁,可以将任务队列按照一定规则(如任务类型)进行分段,每个分段使用独立的锁进行保护。这样不同线程在访问不同分段的任务时不会产生锁竞争,提高并发性能。

示例代码(Java 示例)

import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

class PriorityTask implements Comparable<PriorityTask> {
    private int priority;
    private Runnable task;

    public PriorityTask(int priority, Runnable task) {
        this.priority = priority;
        this.task = task;
    }

    @Override
    public int compareTo(PriorityTask other) {
        return Integer.compare(other.priority, this.priority);
    }

    public void run() {
        task.run();
    }
}

public class PriorityThreadPool {
    private static final int CORE_POOL_SIZE = 5;
    private static final int MAX_POOL_SIZE = 10;
    private static final long KEEP_ALIVE_TIME = 10;

    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            KEEP_ALIVE_TIME,
            TimeUnit.SECONDS,
            new PriorityBlockingQueue<>());

    public static void submitTask(PriorityTask task) {
        executor.submit(task);
    }

    public static void main(String[] args) {
        PriorityTask task1 = new PriorityTask(1, () -> System.out.println("Task with priority 1"));
        PriorityTask task2 = new PriorityTask(2, () -> System.out.println("Task with priority 2"));
        submitTask(task1);
        submitTask(task2);
        executor.shutdown();
    }
}

上述代码实现了一个简单的具有任务优先级管理的线程池,通过 PriorityBlockingQueue 管理任务优先级,并且线程池参数的设置有助于性能优化。