MST

星途 面试题库

面试题:Java固定数目线程池的任务排队机制

在Java的固定数目线程池(如`FixedThreadPool`)中,当所有线程都处于忙碌状态,新的任务到来时,线程池是如何处理这些任务的?请简述其任务排队机制,并举例说明可能导致任务排队出现问题的场景。
12.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 任务处理方式
    • 在Java的FixedThreadPool中,当所有线程都处于忙碌状态,新的任务到来时,这些任务会被放入阻塞队列中等待。FixedThreadPool使用的是LinkedBlockingQueue(无界队列)。
  2. 任务排队机制
    • LinkedBlockingQueue是一个基于链表结构的有界阻塞队列,默认容量为Integer.MAX_VALUE,可认为是无界的。当线程池中的线程都在执行任务时,新任务会不断添加到这个队列中。
    • 线程池中的线程执行完当前任务后,会从队列中取出新任务继续执行。
  3. 可能导致任务排队出现问题的场景
    • 内存耗尽:由于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(先进先出)的,优先级高的任务可能长时间等待低优先级任务执行完毕才能被处理。例如,在一个系统中有监控任务(高优先级)和日志记录任务(低优先级),日志记录任务不断进入队列,导致监控任务可能不能及时执行,影响系统的监控功能。