面试题答案
一键面试设计思路
- 任务优先级管理:
- 定义一个实现
Comparable
接口的任务类,例如PriorityTask
,其中包含任务优先级字段。Comparable
接口的compareTo
方法用于比较任务优先级,使得高优先级任务排在队列前面。 - 使用
PriorityQueue
作为线程池的任务队列,PriorityQueue
会根据任务的优先级自动排序,保证高优先级任务在队列头部,优先被线程获取执行。
- 定义一个实现
- 线程池性能优化 - 避免线程饥饿:
- 采用公平调度策略。可以通过使用
ReentrantLock
的公平锁模式,当任务被提交到线程池时,公平锁会按照任务提交的顺序依次分配给线程执行,避免高优先级任务持续占用资源导致低优先级任务长时间得不到执行。 - 设置合理的线程存活时间。对于核心线程,可以设置为长期存活,保证系统一直有一定数量的线程处理任务;对于非核心线程,设置适当的存活时间,当任务队列空闲时,非核心线程能够及时释放资源,避免资源浪费,同时又能在任务量增加时快速创建线程处理任务,减少任务等待时间。
- 采用公平调度策略。可以通过使用
- 线程池性能优化 - 避免锁竞争:
- 减少锁的粒度。例如,对于任务队列的操作,使用
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
管理任务优先级,并且线程池参数的设置有助于性能优化。