面试题答案
一键面试- 任务处理方式:
- 在Java的
FixedThreadPool
中,当所有线程都处于忙碌状态,新的任务到来时,这些任务会被放入阻塞队列中等待。FixedThreadPool
使用的是LinkedBlockingQueue
(无界队列)。
- 在Java的
- 任务排队机制:
LinkedBlockingQueue
是一个基于链表结构的有界阻塞队列,默认容量为Integer.MAX_VALUE
,可认为是无界的。当线程池中的线程都在执行任务时,新任务会不断添加到这个队列中。- 线程池中的线程执行完当前任务后,会从队列中取出新任务继续执行。
- 可能导致任务排队出现问题的场景:
- 内存耗尽:由于
LinkedBlockingQueue
默认是无界的,如果任务产生的速度持续大于线程处理任务的速度,队列会不断增长,最终可能耗尽系统内存。例如,在一个高并发的Web应用中,大量的请求以非常快的速度到达,而FixedThreadPool
的线程数量有限,新的请求任务不断进入队列,若这种情况持续较长时间,就可能导致内存溢出错误。代码示例如下:
- 内存耗尽:由于
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FixedThreadPoolProblem {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
for (int i = 0; i < Integer.MAX_VALUE; i++) {
final int taskNumber = i;
executorService.submit(() -> {
try {
Thread.sleep(1000);
System.out.println("Task " + taskNumber + " processed.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
executorService.shutdown();
}
}
在上述代码中,FixedThreadPool
只有2个线程,而任务以极快的速度提交,最终可能因为队列不断增长耗尽内存。
- 任务饥饿:如果队列中存在优先级较高的任务,但由于队列是FIFO(先进先出)的,优先级高的任务可能长时间等待低优先级任务执行完毕才能被处理。例如,在一个系统中有监控任务(高优先级)和日志记录任务(低优先级),日志记录任务不断进入队列,导致监控任务可能不能及时执行,影响系统的监控功能。