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

ThreadPoolExecutorJava 中用于管理线程池的类,它实现了 ExecutorService 接口。它可以帮助我们更方便地管理和调度多线程任务的执行。 下面是 ThreadPoolExecutor原理概述: 1. 构造函数:ThreadPoolExecutor 的构造函数接收一些参数,包括核心线程数、最大线程数、任务队列、线程工厂、拒绝策略等。通过这些参数,我们可以配置线程池的大小和行为。 2. 核心线程池:ThreadPoolExecutor 会首先创建核心线程池。核心线程池中的线程数量不会超过核心线程数的设定,即使线程处于空闲状态也不会被回收。 3. 任务队列:当提交一个任务时,如果核心线程池已满,任务会被放入任务队列中等待执行。ThreadPoolExecutor 提供了多种类型的任务队列,如无界队列和有界队列等,可以根据需求进行选择。 4. 最大线程数控制:当任务队列已满时,ThreadPoolExecutor 会根据最大线程数的设定来创建新的线程,直到达到最大线程数。超过最大线程数的任务将会根据指定的拒绝策略进行处理。 5. 执行任务:当有任务可执行时,ThreadPoolExecutor 会从任务队列中取出任务,并将其交给一个空闲的线程执行。如果核心线程池中的线程都在执行任务,新的任务会被放入任务队列中等待。 6. 拒绝策略:当任务队列已满且达到最大线程数时,ThreadPoolExecutor 会根据指定的拒绝策略来处理无法执行的任务。常见的拒绝策略有抛出异常、丢弃任务等。 以上是 ThreadPoolExecutor 的基本原理概述。详细的源码实现可以参考 Java SDK 的源码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java奋斗者

听说打赏我的人再也不会有BUG

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值