面试题答案
一键面试1. 饥饿问题分析
线程饥饿指的是某些任务因为得不到足够的资源(这里是线程资源)而无法执行。在共享线程池场景下,高优先级任务持续不断到来,会导致低优先级任务长时间得不到执行机会。
2. 调整线程池策略避免饥饿问题
- 拒绝策略:通过合理设置拒绝策略,可以在任务无法入队时,采取合适的处理方式,避免任务堆积导致饥饿。例如使用
CallerRunsPolicy
拒绝策略,当线程池饱和且任务队列已满时,将任务回退给调用者线程执行,这样可以保证新任务不会无限堆积,一定程度上缓解饥饿。 - 任务优先级处理:可以在任务类中实现优先级接口,在提交任务时,线程池按照优先级调度任务。例如,使用
PriorityBlockingQueue
作为任务队列,它会按照任务的优先级排序,优先执行高优先级任务,但为了避免低优先级任务饿死,需要配合一定的调度算法。
3. 代码示例
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
class PrioritizedTask implements Callable<String>, Comparable<PrioritizedTask> {
private final int priority;
private final String taskName;
public PrioritizedTask(int priority, String taskName) {
this.priority = priority;
this.taskName = taskName;
}
@Override
public String call() throws Exception {
// 模拟任务执行
Thread.sleep(1000);
return "Task " + taskName + " with priority " + priority + " executed.";
}
@Override
public int compareTo(PrioritizedTask other) {
return Integer.compare(this.priority, other.priority);
}
}
public class ThreadPoolStarvationExample {
public static void main(String[] args) {
int corePoolSize = 2;
int maximumPoolSize = 4;
long keepAliveTime = 10L;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new PriorityBlockingQueue<>();
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
ExecutorService executorService = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
handler);
PrioritizedTask task1 = new PrioritizedTask(1, "Task1");
PrioritizedTask task2 = new PrioritizedTask(2, "Task2");
PrioritizedTask task3 = new PrioritizedTask(3, "Task3");
try {
System.out.println(executorService.submit(task1).get());
System.out.println(executorService.submit(task2).get());
System.out.println(executorService.submit(task3).get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}
}
在上述代码中:
PrioritizedTask
类实现了Callable
和Comparable
接口,通过compareTo
方法定义了任务优先级。- 使用
PriorityBlockingQueue
作为线程池的任务队列,保证高优先级任务优先执行。 - 采用
CallerRunsPolicy
拒绝策略,当线程池和任务队列都满时,任务由调用者线程执行,避免任务无限堆积。