当前位置: 首页 > article >正文

ThreadPoolExecutor的原理?

ThreadPoolExecutor 是 Java 并发包 (java.util.concurrent) 中最常用的实现之一,用于管理和复用一组线程以执行任务。理解 ThreadPoolExecutor 的原理有助于更好地使用和配置线程池。以下是 ThreadPoolExecutor 的核心工作原理:

1. 核心参数

要配置 ThreadPoolExecutor,需要了解以下几个核心参数:

  • corePoolSize:核心线程池大小,即线程池在没有空闲线程的情况下,创建新线程的最大数目。
  • maximumPoolSize:最大线程池大小,即在任务队列满的情况下,为处理任务所能创建的最大线程数。
  • keepAliveTime:线程空闲时间,即非核心线程在没有新任务到达后可以存活的最大时间。
  • unit:上述空闲时间的单位。
  • workQueue:任务队列,存放待执行的任务。
  • threadFactory:用于创建新线程。
  • handler:拒绝策略,当任务无法被执行时使用。

2. 工作原理

ThreadPoolExecutor 的工作原理可以总结为以下几个阶段:

提交任务

当任务被提交到线程池时,会经历以下步骤:

  1. 如果当前运行的线程少于 corePoolSize,即使有空闲线程,也会新建一个线程处理任务。
  2. 如果当前运行的线程数量达到了 corePoolSize,会将任务加入到任务队列 workQueue 中。
  3. 如果任务队列已满且当前运行的线程数量小于 maximumPoolSize,则会新建线程处理任务。
  4. 如果任务队列已满且当前运行的线程数量大于或等于 maximumPoolSize,则会根据拒绝策略 handler 处理新提交的任务。
执行任务
  • 核心线程:始终存活,即使它们在 keepAliveTime 内空闲。
  • 非核心线程:在 keepAliveTime 内空闲会被终止和回收。
示例代码

下面是一个简单的 ThreadPoolExecutor 示例:

import java.util.concurrent.*;

public class ThreadPoolExecutorExample {
    public static void main(String[] args) {
        // 创建线程池,有以下参数
        int corePoolSize = 2;
        int maximumPoolSize = 4;
        long keepAliveTime = 10;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

        ExecutorService threadPool = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                handler);

        // 提交任务
        for (int i = 0; i < 10; i++) {
            final int taskNumber = i;
            threadPool.submit(() -> {
                try {
                    System.out.println("Task " + taskNumber + " is running by " + Thread.currentThread().getName());
                    Thread.sleep(2000);
                    System.out.println("Task " + taskNumber + " is completed by " + Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        // 关闭线程池
        threadPool.shutdown();
        try {
            if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
                threadPool.shutdownNow();
            }
        } catch (InterruptedException ex) {
            threadPool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

3. 拒绝策略

当任务无法提交到线程池时,ThreadPoolExecutor 提供了四种拒绝策略:

  • AbortPolicy(默认):抛出 RejectedExecutionException
  • CallerRunsPolicy:由调用者线程来运行此任务。
  • DiscardPolicy:抛弃当前任务。
  • DiscardOldestPolicy:抛弃队列中最老的任务,然后重新提交当前任务。

4. 任务队列

任务队列的选择影响到任务的执行和拒绝策略的触发时机,可以选择以下几种队列:

  • 直接提交队列(SynchronousQueue):一个不存储元素的阻塞队列,每次插入操作必须等待另一个线程的移除操作。
  • 有界队列(ArrayBlockingQueue):一个有界的阻塞队列,由数组构成。
  • 无界队列(LinkedBlockingQueue):一个基于链接节点的无界阻塞队列。
  • 优先级队列(PriorityBlockingQueue):一个具有优先级的无限阻塞队列。

5. 线程池状态

ThreadPoolExecutor 内部维护着线程池的状态:

  • RUNNING:可以接受新任务并处理排队任务。
  • SHUTDOWN:不接受新任务,但会处理排队的任务。
  • STOP:不接受新任务,不处理排队的任务,并中断正在进行的任务。
  • TIDYING:所有任务都终止,workerCount 为 0,terminated() 方法将被调用。
  • TERMINATEDterminated() 已完成。

总结

ThreadPoolExecutor 提供了一种高效的线程管理方式,通过明确的配置参数,可以灵活地适应不同的并发场景和任务需求。了解其工作原理和使用方法,有助于在开发中更有效地利用线程资源,提高程序的性能和稳定性。


http://www.kler.cn/a/320092.html

相关文章:

  • ​​​​​​​​​​​​​​★3.3 事件处理
  • 网络安全——常用语及linux系统
  • ASP.NET Core - IStartupFilter 与 IHostingStartup
  • Franka例程学习——force_control
  • SpeingMVC框架(三)
  • 【Rust自学】12.2. 读取文件
  • 【大数据】元数据是解锁数据价值的关键
  • JPA+Thymeleaf增删改查
  • WPF 绑定 DataGrid 里面 Button点击事件 TextBlock 双击事件
  • 免杀笔记 ---> 无痕Hook?硬件断点 Syscall!
  • Git 的安装和配置
  • Ubuntu下TexMaker发生CTeX fontset `fandol‘ is unavailable问题
  • SpringSecurity-用户认证
  • JAVA基础语法 day07
  • 全能通人工智能的能力评估框架-Levels of AGI: Operationalizing Progress on the Path to AGI
  • 欺诈文本分类检测(十六):支持分类原因评测改造
  • 面经 | 手写
  • 口语笔记——被动语态
  • spring boot 项目中redis的使用,key=value值 如何用命令行来查询并设置值。
  • 001、restful设计规范
  • OpenHarmony(鸿蒙南向)——平台驱动开发【SDIO】
  • golang雪花算法实现64位的ID
  • JWT(JSON Web Tokens) 详细介绍
  • LeetCode - 503 下一个更大元素 II
  • 使用iTextPDF库实现矩形框和打勾符号(√)
  • 【网络安全】更改参数实现试用计划延长