java线程池详解

在 Java 中,线程池的核心是 java.util.concurrent 包中的 ThreadPoolExecutor 类。它通过线程复用、任务排队、线程数量控制等机制,提高了资源利用率和系统响应能力。Java 提供了一些常用线程池的封装,如通过 Executors 工厂类来创建。我们将详细讲解:


一、线程池核心参数详解(ThreadPoolExecutor

public ThreadPoolExecutor(
    int corePoolSize,             // 核心线程数
    int maximumPoolSize,          // 最大线程数
    long keepAliveTime,           // 非核心线程存活时间
    TimeUnit unit,                // 存活时间单位
    BlockingQueue workQueue, // 任务队列
    ThreadFactory threadFactory,  // 线程工厂
    RejectedExecutionHandler handler // 拒绝策略
)

二、任务队列(BlockingQueue)

队列类型 特点 使用场景
ArrayBlockingQueue 有界数组队列 任务量可控,防止内存溢出
LinkedBlockingQueue 可选大小,默认无界 高吞吐任务,避免频繁线程创建
SynchronousQueue 不存储任务,直接提交给线程 高并发、低延迟
PriorityBlockingQueue 可排序任务队列 有优先级的任务

三、拒绝策略(RejectedExecutionHandler)

拒绝策略 含义
AbortPolicy(默认) 抛出 RejectedExecutionException
CallerRunsPolicy 由提交任务的线程执行该任务
DiscardPolicy 直接丢弃任务
DiscardOldestPolicy 丢弃队列头部最老的任务,尝试提交新任务

四、Java 提供的线程池(通过 Executors 工厂方法)

1. Executors.newFixedThreadPool(nThreads)

  • 特性:固定大小线程池,使用 LinkedBlockingQueue

  • 适用场景:执行长期任务,线程数固定,控制最大并发数。

2. Executors.newCachedThreadPool()

  • 特性:线程数几乎无限制(Integer.MAX_VALUE),使用 SynchronousQueue

  • 适用场景:短时间大量任务,线程能及时回收。

3. Executors.newSingleThreadExecutor()

  • 特性:只有一个线程,任务顺序执行,使用 LinkedBlockingQueue

  • 适用场景:需要顺序执行任务的场景(如日志处理)。

4. Executors.newScheduledThreadPool(n) / Executors.newSingleThreadScheduledExecutor()

  • 特性:支持任务延迟执行和定时执行。

  • 适用场景:定时任务或周期性任务。

  • ScheduledThreadPoolExecutor 内部使用 DelayedWorkQueue,是一个基于时间优先级的无界阻塞队列,实现了 DelayQueue(总是从队列头部(最小堆堆顶)查看最近任务。没到时间:阻塞等待 delay 时间。到时间了:返回任务,执行。

  • 底层是**最小堆(小顶堆)**结构。

  • 所有任务都实现了 Delayed 接口,根据“下一次触发时间”排序。


五、实际场景下推荐线程池参数配置

CPU 密集型任务

  • 如:图像处理、复杂计算

  • 推荐配置

    int core = Runtime.getRuntime().availableProcessors();
    new ThreadPoolExecutor(core, core,
        0L, TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue<>(), 
        Executors.defaultThreadFactory(), 
        new AbortPolicy());
    
  • 理由:避免过多线程上下文切换,核心线程数 = CPU核数。


IO 密集型任务

  • 如:数据库访问、网络调用、文件操作

  • 推荐配置

    int core = Runtime.getRuntime().availableProcessors() * 2;
    new ThreadPoolExecutor(core, core * 2,
        60L, TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(1000), 
        Executors.defaultThreadFactory(), 
        new CallerRunsPolicy());
    
  • 理由:IO阻塞时间长,可以适当增加线程数。结合限队列防止OOM。


高并发突发请求(如网关服务)

  • 推荐配置

    new ThreadPoolExecutor(100, 200,
        30L, TimeUnit.SECONDS,
        new SynchronousQueue<>(), 
        Executors.defaultThreadFactory(), 
        new AbortPolicy());
    
  • 理由:采用直传任务队列,线程资源敏感,快速拒绝新任务(避免系统雪崩)。


日志、消息队列消费者(顺序性任务)

  • 推荐配置

    Executors.newSingleThreadExecutor();
    
  • 理由:顺序执行任务,避免并发问题。


定时任务或周期性任务

  • 推荐配置

    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
    scheduler.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
    
  • 理由:周期任务机制内置支持,适用于监控、清理等任务。


六、建议使用自定义线程池(不要直接用 Executors

原因:

  • Executors.newFixedThreadPool()newSingleThreadExecutor() 使用 无界队列 → 可能导致 OOM。

  • newCachedThreadPool() 使用 最大线程数无上限 → 易耗尽系统资源。

推荐封装:

public class ThreadPoolFactory {
    public static ThreadPoolExecutor createIoThreadPool(String name) {
        return new ThreadPoolExecutor(8, 16,
            60, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(2000),
            new NamedThreadFactory(name),
            new CallerRunsPolicy());
    }
}

七、总结推荐表格

场景 核心线程 最大线程 队列类型 拒绝策略 说明
CPU 密集 CPU 核数 核数 LinkedBlockingQueue AbortPolicy 控制上下文切换
IO 密集 核数×2 核数×2~4 有界队列 CallerRunsPolicy 防止内存膨胀
高并发 高并发数 高并发×2 SynchronousQueue AbortPolicy 快速失败
顺序执行 1 1 LinkedBlockingQueue AbortPolicy 保证顺序
定时任务 按需设置 按需设置 - - 使用 ScheduledThreadPool

如果你有具体的业务场景(如消息队列消费、Web接口处理、批量处理等),我可以帮你单独设计一个更合理的线程池配置,想要吗?

你可能感兴趣的:(面试准备-内容整理背诵,python,开发语言)