ThreadPoolExecutor - 管理线程池的核心类

news2024/11/26 14:37:18

下面是使用给定的初始参数创建一个新的 ThreadPoolExecutor (构造方法)。

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

形参:

  • corePoolSize – 要保留在池中的线程数,即使它们处于空闲状态,除非 allowCoreThreadTimeOut 被设置了。
    allowCoreThreadTimeOut 是一个开关,用于控制核心线程是否可以在空闲状态下超时并被终止。默认情况下,allowCoreThreadTimeOut 是 false,这意味着核心线程不会因为空闲而超时被销毁。如果你调用
    setAllowCoreThreadTimeOut(true),那么核心线程也会像非核心线程一样,在空闲一段时间后(由
    keepAliveTime 和 unit 参数指定)被终止。
  • maximumPoolSize – 池中允许的最大线程数
  • keepAliveTime – 当线程数大于核心数时,这是多余的空闲线程在终止之前等待新任务的最长时间。
  • unit – 参数的时间 keepAliveTime 单位
  • workQueue – 用于在任务执行之前保存任务的队列。这个队列将仅保存通过 execute 方法提交的 Runnable 任务和通过
    submit 方法提交的 Runnable 或 Callable 任务。 execute 方法只接受 Runnable 任务。execute 方法没有返回值。适用于不需要返回结果的任务。
    submit 方法可以接受 Runnable 或 Callable 任务。submit 方法返回一个 Future 对象。
    如果提交的是 Runnable 任务,Future.get() 方法返回 null。
    如果提交的是 Callable 任务,Future.get() 方法返回 call 方法的返回值。
    适用于需要返回结果或检查任务状态的任务。
  • threadFactory – 执行器创建新线程时使用的工厂
  • handler – 当线程边界和队列容量已达到上限导致执行被阻塞时使用的处理程序。 handler 是
    RejectedExecutionHandler 接口的实现类对象。

在这里插入图片描述
RejectedExecutionHandler 接口的 rejectedExecution() 方法一共有四种默认实现:
在这里插入图片描述

在这里插入图片描述

  1. AbortPolicy - Abort 意思为中止
  • 类名:java.util.concurrent.ThreadPoolExecutor.AbortPolicy
  • 描述:这种策略在任务不能被执行时,会抛出 RejectedExecutionException 异常。它是默认的拒绝策略。
    使用场景:适用于不能丢弃任务且需要立即知道任务被拒绝的情况。
public static class AbortPolicy implements RejectedExecutionHandler {
    public AbortPolicy() { }
    
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() +
                                             " rejected from " +
                                             e.toString());
    }
}
  1. CallerRunsPolicy
  • 类名:java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy
  • 描述:这种策略在任务不能被执行时,会由提交任务的线程(通常是调用 execute 方法的线程)来执行该任务。这种策略可以有效降低新任务的流量,避免任务丢失。
    使用场景:适用于可以接受任务执行延迟但不希望任务被丢弃的情况。
public static class CallerRunsPolicy implements RejectedExecutionHandler {
    public CallerRunsPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}
  1. DiscardOldestPolicy
  • 类名:java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy
  • 描述:这种策略在任务不能被执行时,会丢弃队列中最旧的未处理任务,然后尝试重新提交被拒绝的任务。
    使用场景:适用于希望优先处理新任务可以接受丢弃旧任务的情况。
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    public DiscardOldestPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll();
            e.execute(r);
        }
    }
}
  1. DiscardPolicy
  • 类名:java.util.concurrent.ThreadPoolExecutor.DiscardPolicy
  • 描述:这种策略在任务不能被执行时,会直接丢弃被拒绝的任务,不会有任何异常抛出。
    使用场景:适用于可以接受任务丢弃且不希望处理被拒绝任务的情况。
public static class DiscardPolicy implements RejectedExecutionHandler {
    public DiscardPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        // Do nothing
    }
}

总结:

  • AbortPolicy:直接抛出 RejectedExecutionException 异常。
  • CallerRunsPolicy:由提交任务的线程执行被拒绝的任务。
  • DiscardOldestPolicy:丢弃队列中最旧的任务,然后重新提交被拒绝的任务。
  • DiscardPolicy:直接丢弃被拒绝的任务,不抛出异常。

下面是四种对于上述的ThreadPoolExecutor的封装,ExecutorService是线程服务对象

  1. 创建固定数量的线程对象newFixedThreadPool()
ExecutorService executorService = Executors.newFixedThreadPool(3);
    /**
	创建一个线程池,该线程池重用在共享的无界队列上运行的固定数量的线程。在任何时候,大多数 nThreads 线程都将是活动的去处理任务。
	如果在所有线程都处于活动状态时提交了其他任务,它们将在队列中等待,直到线程可用。
	如果某个线程在关闭之前由于执行期间的故障而终止,那么如果需要执行后续任务,将会有一个新的线程替代它的位置。
	这段话解释了固定大小线程池的一个重要特性:线程池会维护固定数量的线程,即使其中某个线程由于运行时的异常或错误而终止,线程池也会创建一个新的线程来替换它,从而确保线程池中始终有固定数量的线程来处理任务。
		形参:
		nThreads – 池中的线程数
		返回值:
		新创建的线程池
		抛出:
		IllegalArgumentException –如果 nThreads <= 0
     */
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS, // 毫秒
                                      new LinkedBlockingQueue<Runnable>());
    }

ThreadPoolExecutor(nThreads)
核心线程数:nThreads
最大线程数:nThreads
队列类型:LinkedBlockingQueue(无界队列)FIFO先进先出队列
行为:固定数量的线程处理任务。如果所有线程都在忙碌,新任务会被放入无界队列中等待。
适用场景:适用于需要稳定的线程数量来处理较为均匀的任务负载的场景。

  1. 根据需求动态创建线程newCachedThreadPool, 创建的线程可以重复使用,只是当目前线程不够了他会动态增加线程
ExecutorService executorService = Executors.newCachedThreadPool();
/*
创建一个可以根据需要创建新线程的线程池,但如果之前构造的线程可用,则会重用这些线程。
这种线程池通常会提升那些执行许多短暂异步任务的程序的性能。
调用 execute 方法时,如果有可用的线程,会重用之前构造的线程。如果没有可用的线程,则会创建一个新线程并添加到线程池中。

未使用超过60秒的线程会被终止并从缓存中移除。
因此,一个长时间处于空闲状态的线程池将不会消耗任何资源。
需要注意的是,可以使用 ThreadPoolExecutor 构造函数创建具有类似属性但不同细节(例如超时参数)的线程池。

返回值:
新创建的线程池
*/
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

newCachedThreadPool()
核心线程数:0
最大线程数:Integer.MAX_VALUE
队列类型:SynchronousQueue(不存储任务的队列,每次插入操作都必须等待对应的删除操作,反之亦然)。
每个 put 操作(插入任务)必须等待一个 take 操作(移除任务),相应地,每个 take 操作必须等待一个 put 操作。换句话说,生产者线程和消费者线程必须直接在队列上进行任务的交接。
行为:线程池可根据需求动态创建新线程,闲置超过 60 秒的线程会被终止并移出缓存。
适用场景:适用于大量短期异步任务或任务负载波动较大的场景。

newCachedThreadPool() 的工作原理:
① 任务提交:
当一个任务被提交到 newCachedThreadPool() 时,它会尝试将任务放入 SynchronousQueue。
由于 SynchronousQueue 不存储任务,这意味着必须有一个线程立即接收这个任务。
② 线程创建:
如果当前没有空闲线程能够立即接收任务,newCachedThreadPool() 会创建一个新的线程来处理这个任务。
这种机制确保了任务可以尽快得到处理。
③ 线程回收:
新创建的线程如果在闲置超过 60 秒后没有接收到新的任务,就会被终止并移出线程池。
这有助于释放资源,避免不必要的线程占用。

newCachedThreadPool() 完全依赖非核心线程来处理任务

  1. 单一线程newSingleThreadExecutor
ExecutorService executorService = Executors.newSingleThreadExecutor();
/*
创建一个 Executor,它使用单个工作线程从一个无界队列中获取任务进行操作。
(但是请注意,如果这个单个线程在执行过程中因为故障而在关闭之前终止了,那么如果需要执行后续任务,将会有一个新的线程替代它的位置。)
任务保证按顺序执行,并且在任何给定时间点,不会有超过一个任务在运行。
与功能相似的 newFixedThreadPool(1) 不同,返回的执行器保证不会被重新配置为使用额外的线程。

返回值:
新创建的单线程执行器
*/
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS, // 毫秒
                                    new LinkedBlockingQueue<Runnable>()));
    }
private static class FinalizableDelegatedExecutorService
            extends DelegatedExecutorService {
        FinalizableDelegatedExecutorService(ExecutorService executor) {
            super(executor);
        }
        @SuppressWarnings("deprecation")
        protected void finalize() {
            super.shutdown();
        }
    }
private static class DelegatedExecutorService
            implements ExecutorService {
        private final ExecutorService e;
        DelegatedExecutorService(ExecutorService executor) { e = executor; }

newSingleThreadExecutor()
核心线程数:1
最大线程数:1
队列类型:LinkedBlockingQueue(无界队列)
行为:始终只有一个线程执行任务,任务按提交顺序执行。如果线程因故障终止,会创建一个新线程来替代它。
适用场景:适用于需要按顺序执行任务的场景,并且在同一时间只需要一个线程执行任务。

newFixedThreadPool(1):虽然初始时只有一个线程,但它是使用 ThreadPoolExecutor 实现的,理论上可以通过调用 setCorePoolSize 和 setMaximumPoolSize 方法来重新配置线程池的线程数量。
也就是说,虽然默认情况下只有一个线程,但你可以在运行时增加线程池中的线程数量。
newSingleThreadExecutor():这个执行器保证始终只有一个线程,无法通过重新配置来增加线程数量。
它的实现确保了线程池的单线程性质是不可更改的。

  1. 定时调度线程 newScheduledThreadPool, 线程有3个,但是线程在什么时候执行我们可以去定义他
ExecutorService executorService = Executors.newScheduledThreadPool(3);
/*
	创建一个线程池,该线程池可以计划命令在给定延迟后运行,或定期执行。
	形参:
	corePoolSize – 池中要保留的线程数,即使它们处于空闲状态
	返回值:
	新创建的定时线程池
	抛出:
	IllegalArgumentException –如果 corePoolSize < 0
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
public class ScheduledThreadPoolExecutor
        extends ThreadPoolExecutor
        implements ScheduledExecutorService {
/*
	使用给定的核心池大小创建一个新 ScheduledThreadPoolExecutor 池。
	形参:
	corePoolSize – 要保留在池中的线程数,即使它们处于空闲状态,除非 allowCoreThreadTimeOut 已设置
	抛出:
	IllegalArgumentException –如果 corePoolSize < 0
*/
public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,  // DEFAULT_KEEPALIVE_MILLIS = 10L
              new DelayedWorkQueue());  
        // super父类对象是ThreadPoolExecutor
        // 相当于:
        // public ThreadPoolExecutor(int corePoolSize,
        //                      int maximumPoolSize,
       //                       long keepAliveTime,
        //                      TimeUnit unit,
        //                      BlockingQueue<Runnable> workQueue) {
       // this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
       //      Executors.defaultThreadFactory(), defaultHandler);
    }
    }
 
 }

newScheduledThreadPool(int corePoolSize) 方法用于创建一个定时线程池。
ScheduledThreadPoolExecutor 类继承自 ThreadPoolExecutor,并添加了对定时任务的支持。
核心线程数由 corePoolSize 决定,最大线程数为 Integer.MAX_VALUE
非核心线程的默认存活时间是 10 毫秒。
无界队列:DelayedWorkQueue 是一个无界队列,适用于存储定时任务和周期性任务。即使队列是无界的,它主要是一个优先级队列(基于任务的预定执行时间),并且不会因为任务太多而导致线程池拒绝任务。
超出线程池和等待队列容量的任务会被拒绝,并抛出异常。

newScheduledThreadPool(corePoolSize)
核心线程数:corePoolSize
最大线程数:Integer.MAX_VALUE
队列类型:DelayedWorkQueue(无界优先级队列,基于任务的预定执行时间)
行为:支持定时任务和周期性任务的线程池,核心线程数由 corePoolSize 决定,超出线程池和等待队列容量的任务会被拒绝并抛出异常。线程池可根据需求动态创建新的非核心线程,闲置超过 10 毫秒的线程会被终止并移出缓存,虽然话是这么说,但是由于 DelayedWorkQueue 是一个无界队列,通常情况下不会出现任务队列满的情况,因此非核心线程在 ScheduledThreadPoolExecutor 中被使用的机会较少,就主要还是依赖corePoolSize指定的核心线程来运行任务。因为核心线程先处理不完,然后把任务放到等待队列,等待队列也满了才开非核心线程,我是这样理解的。
适用场景:适用于需要在特定时间点或周期性执行任务的场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1903701.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

缓冲器的重要性,谈谈PostgreSQL

目录 一、PostgreSQL是什么二、缓冲区管理器介绍三、缓冲区管理器的应用场景四、如何定义缓冲区管理器 一、PostgreSQL是什么 PostgreSQL是一种高级的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它以其稳定性、可靠性和高度可扩展性而闻名。它最初由加…

Static关键字的用法详解

Static关键字的用法详解 1、Static修饰内部类2、Static修饰方法3、Static修饰变量4、Static修饰代码块5、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java编程语言中&#xff0c;static是一个关键字&#xff0c;它可以用于多种上…

【Java探索之旅】初识多态_概念_实现条件

文章目录 &#x1f4d1;前言一、多态1.1 概念1.2 多态的实现条件 &#x1f324;️全篇总结 &#x1f4d1;前言 多态作为面向对象编程中的重要概念&#xff0c;为我们提供了一种灵活而强大的编程方式。通过多态&#xff0c;同一种操作可以应用于不同的对象&#xff0c;并根据对象…

数据库系统原理 | 查询作业2

整理自博主本科《数据库系统原理》专业课自己完成的实验课查询作业&#xff0c;以便各位学习数据库系统概论的小伙伴们参考、学习。 *文中若存在书写不合理的地方&#xff0c;欢迎各位斧正。 专业课本&#xff1a; ​ ​ ———— 本次实验使用到的图形化工具&#xff1a;Heidi…

深入分析SSL/TLS服务器的证书(C/C++代码实现)

SSL&#xff08;Secure Sockets Layer&#xff09;和TLS&#xff08;Transport Layer Security&#xff09;是网络安全领域的重要协议&#xff0c;它们在保护网络通信中发挥着至关重要的作用。这些协议通过加密和身份验证机制&#xff0c;确保数据在传输过程中的机密性和完整性…

cs231n作业1——SVM

参考文章&#xff1a;cs231n assignment1——SVM SVM 训练阶段&#xff0c;我们的目的是为了得到合适的 &#x1d44a; 和 &#x1d44f; &#xff0c;为实现这一目的&#xff0c;我们需要引进损失函数&#xff0c;然后再通过梯度下降来训练模型。 def svm_loss_naive(W, …

python基础篇(8):异常处理

在Python编程中&#xff0c;异常是程序运行时发生的错误&#xff0c;它会中断程序的正常执行流程。异常处理机制使得程序能够捕获这些错误&#xff0c;并进行适当的处理&#xff0c;从而避免程序崩溃。 1 错误类型 代码的错误一般会有语法错误和异常错误两种&#xff0c;语法错…

最新整理的机器人相关数据合集(1993-2022年不等 具体看数据类型)

机器人安装数据是指记录全球或特定区域内工业机器人新安装数量的信息&#xff0c;这一数据由国际机器人联合会(IFR)等权威机构定期发布。这些数据不仅揭示了机器人技术的市场需求趋势&#xff0c;还反映了各国和地区自动化水平及产业升级的步伐。例如&#xff0c;数据显示中国在…

nginx相关概念(反向代理、负载均衡)

1 Nginx 是什么 Nginx是一款轻量级的Web 服务器&#xff0c;其特点是占有内存少&#xff0c;并发能力强 2 Nginx 反向代理 正向代理代替客户端去发送请求反向代理代替服务端接受请求 2.1 正向代理 若客户端无法直接访问到目标服务器 server 则客户端需要配置代理服务器 pr…

云渲染技术对电影24帧和游戏60帧渲染需求及时间效率的影响

随着云计算技术的飞速发展&#xff0c;云渲染正重塑着影视和游戏产业的制作流程。它如何影响传统电影24帧和现代游戏60帧的渲染需求与时间效率&#xff1f;本文将深入探讨云渲染带来的变革。 一、电影24帧和游戏60帧作用 电影通常以24帧每秒&#xff08;fps&#xff09;的标准…

数字化精益生产系统--IFS财务管理系统

IFS财务管理系统是一款功能丰富、高效且灵活的企业财务管理软件&#xff0c;广泛应用于多个行业和不同规模的企业中。以下是对IFS财务管理系统的功能设计&#xff1a;

Linux shell编程学习笔记63:free命令 获取内存使用信息

0 前言 在系统安全检查中&#xff0c;内存使用情况也是一块可以关注的内容。Linux提供了多个获取内存信息的命令很多。今天我们先研究free命令。 1 free命令的功能、用法和选项说明 1.1 free命令的功能 free 命令可以显示系统内存的使用情况&#xff0c;包括物理内存、交换…

SSM高校教师教学质量评估系统-计算机毕业设计源码03344

摘要 在高等教育中&#xff0c;教学质量是培养优秀人才的关键。为了提高教学质量&#xff0c;高校需要建立一套科学、有效的教师教学质量评估系统。本研究采用 SSM技术框架&#xff0c;旨在开发一款高校教师教学质量评估系统。 SSM框架作为一种成熟的Java开发框架&#xff0c;具…

入门PHP就来我这(高级)11 ~ MySQL

有胆量你就来跟着路老师卷起来&#xff01; -- 纯干货&#xff0c;技术知识分享 路老师给大家分享PHP语言的知识了&#xff0c;旨在想让大家入门PHP&#xff0c;并深入了解PHP语言。 1 PHP操作MySQL数据库的方法 PHP操作数据库现在用的多的是mysqli拓展库&#xff0c;mysqli扩…

【Python机器学习】模型评估与改进——多分类指标

多分类问题的所有指标基本是上都来自于二分类问题&#xff0c;但是要对所有类别进行平均。多分类的精度被定义为正确分类的样本所占的比例。同样&#xff0c;如果类别是不平衡的&#xff0c;精度并不是很好的评估度量。 想象一个三分类问题&#xff0c;其中85%的数据点属于类别…

可视化作品集(07):网格化管理领域

网格化管理可视化大屏是指利用大屏幕显示设备&#xff0c;通过数据可视化的方式展示网格化管理的相关信息和指标。网格化管理是一种以网格为基础的城市管理模式&#xff0c;通过将城市划分为不同的网格单元&#xff0c;实现对城市各项管理工作的全覆盖、全时空监控和全过程管理…

中国星坤X1224系列线对板连接器:小巧稳定,助力物联网终端高效运行

在物联网、电器和消防等领域&#xff0c;终端设备的安全稳定运行至关重要。为了满足这些领域对连接器高可靠性、小巧轻便和耐高温的需求&#xff0c;X1224系列线对板连接器应运而生。这款连接器以其独特的设计和卓越的性能&#xff0c;成为了终端设备中不可或缺的一部分。 一、…

中英双语介绍加拿大(Canada)

加拿大国家简介 中文版 加拿大简介 加拿大是位于北美洲北部的一个国家&#xff0c;以其广袤的土地、多样的文化和自然美景著称。以下是对加拿大的详细介绍&#xff0c;包括其地理位置、人口、经济、特色、高等教育、著名景点、国家历史和交通条件。 地理位置 加拿大是世界…

Day2用 rustlings 练习 Rust 语言-Move Semantics

大家好 今天 完成 2024年自动驾驶OS开发训练营-初阶营第四期-导学 Day2用 rustlings 练习 Rust 语言 -Move Semantics https://doc.rust-lang.org/stable/book/ch04-00-understanding-ownership.html 提交代码时候 提示 没有权限怎么出来 aciton 参考开发环境配置 https://rcor…

建投数据入选“2024年中国最佳信创企业管理软件厂商”

近日&#xff0c;建投数据凭借国产化自主知识产权、完备的信创资质及信创软硬件环境全栈适配能力&#xff0c;入选第一新声联合天眼查发布的“2024年中国最佳信创厂商系列榜单”细分行业榜之“最佳信创企业管理软件厂商”。 本次最佳信创厂商系列榜单评选&#xff0c;包括综合榜…