Java线程池详解

2025-12-12 0 537

阅读本文前,建议先阅读《Java 线程与原理》了解 Java 线程的基本使用(ThreadRunnableCallableFutureTask的关系)

Executor 框架

Executor 框架是 Java 5 引入的并发工具,位于 java.util.concurrent 包中,其核心目标是将线程任务的提交与任务的执行解耦,是 Java 线程池的核心实现框架。

Executor 框架的核心接口:

  • Executor:最顶层的接口,定义了 execute(Runnable command) 方法。
public interface Executor {
    void execute(Runnable command);
}
  • ExecutorService:扩展了 Executor,增加了管理线程池生命周期的方法(如 shutdown()submit()invokeAll() 等)。
public interface ExecutorService extends Executor {
     Future submit(Callable task);
    List shutdownNow();
    boolean awaitTermination(long timeout, TimeUnit unit);
    // ...
}
  • ScheduledExecutorService:支持延迟或周期性执行任务。
public interface ScheduledExecutorService extends ExecutorService {
    ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit);
    ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
    // ...
}
  • ThreadPoolExecutor:ExecutorService 的核心实现类,提供了丰富的线程池配置选项。

接口与类关系:

Executor 框架的使用示意图:

ThreadPoolExecutor

构造函数:

public ThreadPoolExecutor(
    int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue workQueue,
    ThreadFactory threadFactory,
    RejectedExecutionHandler handler
)

参数说明:

参数 说明
corePoolSize 核心线程数。即使空闲,这些线程也不会被回收(除非设置 allowCoreThreadTimeOut(true))。当低于这个数值,总是新建线程执行任务;超过这个数值后,会把任务放到 workQueue排队,当队列满时,才在 maximumPoolSize 范围内新建线程执行任务。
maximumPoolSize 最大线程数。当活动线程数达到这个数值后,将会被拒绝掉(见后面的 RejectedExecutionHandler )。
keepAliveTime 非核心线程闲置时的超时时长。超过这个时长,闲置的非核心线程就会被回收。
unit keepAliveTime 参数的时间单位,有 TimeUnit.MILLISECONDTimeUnit.SECONDTimeUnit.MINUTE
workQueue 任务队列,用于缓存待执行的任务。常用实现:1、ArrayBlockingQueue:基于数组结构的的先进先出有界阻塞队列,此队列创建时必须指定大小。2、LinkedBlockingQueue:基于链表结构的先进先出无界阻塞队列,如果创建时没有指定此队列大小,则默认为 Integer.MAX_VALUE 。3、SynchronousQueue:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态。相当于队列容量大小为 1 。4、PriorityBlockingQueue:一个具有优先级的无限阻塞队列,可用于设置任务处理的优先级。
threadFactory 线程工厂,用于自定义线程创建(如命名、优先级等)。
handler 拒绝策略,当线程池和队列都满时如何处理新任务。常用实现:1、AbortPolicy(默认):丢弃任务,并抛出 RejectedExecutionException 异常。2、DiscardPolicy:也是丢弃任务,但是不抛出异常。3、DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)4、CallerRunsPolicy:由调用线程处理该任务

ThreadPoolExecutor 线程池处理流程:


ThreadPoolExecutor 线程池使用示例:

import java.util.concurrent.*;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ThreadFactory namedThreadFactory = r -> {
            Thread t = new Thread(r, \"MyPool-Thread\");
            t.setDaemon(false);
            return t;
        };

        BlockingQueue workQueue = new ArrayBlockingQueue(100);
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2,
            4,
            30,
            TimeUnit.SECONDS,
            workQueue,
            namedThreadFactory,
            handler
        );

        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            executor.submit(() -> {
                System.out.println(\"Task \" + taskId + \" executed by \" + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        executor.shutdown();
    }
}

Executors 工厂类

Java 提供了 Executors 工具类,用于快速创建常见线程池:

方法 说明 内部实现
newFixedThreadPool(int n) 固定大小线程池 core = max = n,无界队列
newCachedThreadPool() 缓存线程池 core = 0,max = Integer.MAX_VALUE,SynchronousQueue
newSingleThreadExecutor() 单线程池 core = max = 1,无界队列
newScheduledThreadPool(int n) 支持定时/周期任务 ScheduledThreadPoolExecutor

其中,newFixedThreadPoolnewCachedThreadPool 在高负载下可能导致 OOM(因使用无界队列或过多线程)。因此,生产环境强烈建议手动创建 ThreadPoolExecutor 并明确参数。

ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor 是专门用于延迟执行或周期性执行任务。它是 ThreadPoolExecutor 的子类,同时实现了 ScheduledExecutorService 接口。

ScheduledThreadPoolExecutor 特性:

  • 支持一次性延迟执行。
  • 支持 固定频率(fixed-rate)或 固定延迟(fixed-delay)的周期性任务。
  • 线程复用:多个定时任务共享线程池中的线程,避免频繁创建/销毁线程。
  • 线程池等待队列默认使用 DelayedWorkQueue(一种无界优先队列),大量任务堆积可能导致 OOM。
  • 比 Timer / TimerTask 更安全、更灵活(Timer 是单线程,异常会导致整个调度器崩溃)。若某个任务抛出未捕获异常,该任务将终止,但不会影响其他任务。
  • 可通过 ScheduledFuture.cancel() 取消任务。
  • 调用 shutdown() 关闭线程池后,已提交的任务仍会执行;shutdownNow() 尝试中断正在执行的任务。

线程池最佳实践

  • 避免使用 Executors 创建普通线程池,应显式使用 ThreadPoolExecutor
  • 合理设置 corePoolSize 和 maximumPoolSize,根据 CPU 核心数和任务类型(CPU 密集型 vs IO 密集型)调整。
  • 使用有界队列,防止内存溢出。
  • 自定义 ThreadFactory,为线程命名便于排查问题。
  • 合理处理异常:在 RunnableCallable 中捕获异常,避免线程静默退出。
  • 优雅关闭线程池
executor.shutdown();
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
    executor.shutdownNow();
}

参考

  • 《Java并发编程的艺术》

【本文首发于:JavaArchJourney】

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 Java线程池详解 https://www.zuozi.net/36048.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务