ScheduledThreadPoolExecutor 及 ThreadPoolExecutor的基本使用及说明

这篇具有很好参考价值的文章主要介绍了ScheduledThreadPoolExecutor 及 ThreadPoolExecutor的基本使用及说明。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。

ScheduledThreadPoolExecutor 及 ThreadPoolExecutor的基本使用及说明,java学习之路,java,android,ThreadPool,线程池,面试

一、导读

我们继续总结学习Java基础知识,温故知新。

本文讲述 ScheduledThreadPoolExecutor 及 ThreadPoolExecutor。

二、概览

我们并不推荐使用Executors去创建线程池,为了更好地控制和管理线程池,通过ThreadPoolExecutor或者ScheduledThreadPoolExecutor的方式去创建线程池。这两种方式可以根据具体的需求设置线程池的参数,例如核心线程数、最大线程数、队列类型等,以及自定义拒绝策略来处理任务无法执行的情况。

2.1 为什么不推荐使用Executors去创建线程池

newFixedThreadPool(固定线程数)
newSingleThreadExecutor(单线程)
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。线程数固定,任务多了之后容易堆积。

newCachedThreadPool(可缓存的线程池)
newScheduledThreadPool(定时执行的线程池)
主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。不限定线程多数量,任务一多,容易创建无限多线程。

三、使用

ScheduledThreadPoolExecutor 及 ThreadPoolExecutor的基本使用及说明,java学习之路,java,android,ThreadPool,线程池,面试

3.1 ThreadPoolExecutor

public class ThreadPoolDemo {
    private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
      2,   // 核心线程数
      10,  // 最大线程数
      10L, // 线程 存活时间
      TimeUnit.SECONDS,  // 线程存活时间单位
      new LinkedBlockingQueue(100));// 缓冲队列
    
    public static void main(String[] args) {
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
            }
        });
    }
}

构造方法

public ThreadPoolExecutor(
    // 线程池核心线程数
    int corePoolSize, 
    // 线程池最大数
    int maximumPoolSize, 
    // 空闲线程存活时间
    long keepAliveTime,  
    // 时间单位
    TimeUnit unit,
    // 线程池所使用的缓冲队列
    BlockingQueue<Runnable> workQueue,
    // 线程池创建线程使用的工厂
    ThreadFactory threadFactory,
    // 线程池对拒绝任务的处理策略
    RejectedExecutionHandler handler)

处理任务的优先级为核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

3.2 ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor 是 Java 8 引入的一个新特性,继承自ThreadPoolExecutor。
它们都提供了一些基本的线程池操作,如 execute() 方法用于执行任务,schedule() 方法用于延迟定时执行任务。
不同之处在于 ScheduledThreadPoolExecutor 可以根据指定的周期和时间间隔来调度任务执行,从而实现周期性执行任务的效果。

ScheduledThreadPoolExecutor用于替代Timer,比Timer更强大,更灵活,Timer对应的是单个后台线程,而ScheduledThreadPoolExecutor可以在构造函数中指定多个对应的后台线程数。

ScheduledThreadPoolExecutor 内部构造了两个内部类 ScheduledFutureTask 和 DelayedWorkQueue,基于这两个类实现。

有两种创建方式:

3.2.1 通过构造方法创建

new ScheduledThreadPoolExecutor(int corePoolSize, // 核心线程数
                                ThreadFactory threadFactory, //主要作用是用来捕获异常和设置线程名称
                                RejectedExecutionHandler handler) //拒绝策略


ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.execute(...);
executor.shutdown(...);
executor.schedule(...);
executor.scheduleAtFixedRate(...);
executor.scheduleWithFixedDelay(...);
executor.submit(...);

3.2.2 通过Executors工厂方法创建

方式一:
newSingleThreadScheduledExecutor() 只有一个工作线程的线程池。如果内部工作线程由于执行周期任务异常而被终止,则会新建一个线程替代它的位置。


方式二:
Executors.newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)


ScheduledExecutorService service = Executors.newScheduledThreadPool(1);

service.execute(...);
service.shutdown(...);
service.schedule(...);
service.scheduleAtFixedRate(...);
service.scheduleWithFixedDelay(...);
service.submit(...);

我们常用的方法有以下一些


/**
  创建并执行在给定延迟后启用的一次性操作
 * @param command 执行的任务
 * @param delay 延迟的时间
 * @param unit 延迟的时间单位
 */
schedule(Runnable command, long delay, TimeUnit unit)


周期任务,在第一次执行完之后延迟delay后开始下一次执行,重点是任务执行完后才开始下一次。
如果任务执行过程抛出异常,不会再执行该任务!
/**
  定时执行 周期任务,
  在initialDelay后开始调度该任务,任务执行完成后,延迟 delay 时间再次执行
  
 * @param command 执行的任务
 * @param initialDelay 初始延迟的时间
 * @param delay 延迟的时间
 * @param unit 延迟的时间单位
 */
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)


周期任务,第一次执行延期时间为initialDelay,之后每隔period执行一次
如果任务执行过程抛出异常,不会再执行该任务!
/**
  按照固定的评率定时执行周期任务,不受任务运行时间影响。
  在initialDelay后开始调度该任务,然后 delay 时间后再次执行
  
  如果任务执行的时间比period长的话,会导致该任务延迟执行,不会同时执行
 * @param command 执行的任务
 * @param initialDelay 初始延迟的时间
 * @param period 延迟的时间
 * @param unit 延迟的时间单位
 */
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)

ScheduledThreadPoolExecutor 有两个关闭策略:

  1. 关闭策略 1:在任务队列为空时,调用 shutdown() 方法关闭线程池。
  2. 关闭策略 2:当线程池中的所有任务都执行完毕时,调用 shutdown() 方法关闭线程池。

这两个关闭策略的区别在于,当线程池中的任务队列为空时,调用 shutdown() 方法关闭线程池可以立即关闭线程池,避免了等待任务执行完毕的时间开销。而当线程池中的任务都执行完毕时,调用 shutdown() 方法关闭线程池则无法立即关闭线程池,需要等待所有任务执行完毕后才能关闭线程池。

其他的比较简单,就不列出来。

使用 ScheduledThreadPoolExecutor 时一定要注意异常处理, 如果使用不当,会导致定时任务不再执行。

3.2.3 ScheduledThreadPoolExecutor与ThreadPoolExecutor异同

  1. ThreadPoolExecutor 是一个普通的线程池实现,用于执行提交的任务。它不提供定时调度任务的功能。而ScheduledThreadPoolExecutor 是ThreadPoolExecutor的子类,它扩展了线程池的功能,可以执行延迟任务和定时任务。
  2. ThreadPoolExecutor 是基于工作队列的线程池,它使用工作队列来保存需要执行的任务,并通过线程池中的工作线程来执行这些任务。ScheduledThreadPoolExecutor 在ThreadPoolExecutor的基础上添加了一个调度器,用于管理延迟任务和定时任务的执行。
  3. ThreadPoolExecutor 默认情况下是懒汉式创建线程,即在需要执行任务时才创建线程;而ScheduledThreadPoolExecutor 在初始化时就会一次性创建指定数量的线程,这些线程会一直存在,用于执行被调度的任务。

四、 推荐阅读

Java 专栏

SQL 专栏

数据结构与算法

Android学习专栏

ScheduledThreadPoolExecutor 及 ThreadPoolExecutor的基本使用及说明,java学习之路,java,android,ThreadPool,线程池,面试文章来源地址https://www.toymoban.com/news/detail-616362.html

到了这里,关于ScheduledThreadPoolExecutor 及 ThreadPoolExecutor的基本使用及说明的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Eigen库的基本使用说明(二)

     之前的文章中,简单的介绍了一些基本的操作,回归之前的内容可以参考一下链接: zEigen库的基本使用说明_每日亿学的博客-CSDN博客_eigen库  本章内容主要就是继续延伸Eigen库的使用内容也会实时进行更新,Eigen库在SLAM中使用广泛,需要对这个库有一定的熟悉。 首先最简单

    2023年04月22日
    浏览(35)
  • ThreadPoolExecutor使用浅谈

    ThreadPoolExecutor 是Python标准库 concurrent.futures 模块中的一个类,用于实现线程池的功能。 ThreadPoolExecutor 模块相比于 threading 等模块,通过 submit 方法返回的是一个 Future 对象,它代表了一个未来可期的结果。通过 Future 对象,我们可以在主线程(或主进程)中获取某个线程(或任

    2024年02月06日
    浏览(33)
  • Java多线程 - 创建线程池的方法 - ThreadPoolExecutor和Executors

    线程池介绍 什么是线程池 ? 线程池就是一个可以复用线程的技术。 不使用线程池的问题 : 如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能。 线程池工作原理 : 例如线程池

    2023年04月16日
    浏览(46)
  • URI、URL、URIBuilder、UriBuilder、UriComponentsBuilder说明及基本使用

    之前想过直接获取url通过拼接字符串的方式实现,但是这种只是暂时的,后续地址如果有变化或参数很多,去岂不是要拼接很长,由于这些等等原因,所以找了一些方法实现 URI全称是Uniform Resource Identifier,也就是统一资源标识符,它是一种采用特定的语法标识一个资源的字符

    2024年02月11日
    浏览(39)
  • concurrent.futures模块ThreadPoolExecutor、ProcessPoolExecutor讲解及使用实例

    这个模块是python并发执行的标准库,具有线程池和进程池、管理并行编程任务、处理非确定性的执行流程、进程/线程同步等功能。 模块组成 1、concurrent.futures.Executor: 这是一个虚拟基类,提供了异步执行的方法。 2、submit(function, argument): 调度函数(可调用的对象)的执行,将

    2024年02月14日
    浏览(33)
  • ScheduledThreadPoolExecutor 定时任务

    目录 ScheduledThreadPoolExecutor 一、概述 二、常用方法 1、schedule 方法 2、scheduleAtFixedRate方法 3.scheduleWithFixedDelay方法 三、ScheduledExecutorService的创建方式 java 中ScheduledExecutorService接口是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务

    2024年03月18日
    浏览(47)
  • 深入理解高并发编程 - 深度解析ScheduledThreadPoolExecutor

    ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor 并实现了 ScheduledExecutorService 接口,这使得它可以同时充当线程池和定时任务调度器。 构造方法接收一个 corePoolSize 参数,它表示线程池中的核心线程数。核心线程是一直保持存活的线程,即使没有任务执行,以便支持定时任务的调

    2024年02月12日
    浏览(48)
  • eDiary-白日梦电子记事本基本使用说明【记事本导出和导入方法、本地数据迁移方法、记录工作日报、日历代办等】

    因为公司大佬分享资料,需要用到白日梦这个电子记事本,所以才了解到这个软件,体量小,功能高级,是个好软件。 官方地址:白日梦 导出与导入均不要使用文件-导出和导入,不好使。 右键需要导出的文档-高级-导出-文件 跟着提示下一步就行了 我这以导入文件夹资料为

    2024年02月03日
    浏览(125)
  • 小景的工具使用--Java诊断工具Arthas的使用说明

    小景最近在做程序和数据库的压测工作,期间监控压测数据,分析程序原因变成了一个待解决的问题,根据公司小伙伴的建议,接触了阿尔萨斯这个诊断工具,下面小景分别基于Linux操作系统和Windows操作系统,来详细的说下使用说明和使用心得。   Arthas(阿尔萨斯)是一个用

    2024年02月08日
    浏览(40)
  • kafka 命令脚本说明以及在java中使用

    1、关于topic,这里用window 来示例 2、创建 first topic,五个分区,1个副本 3、查看当前服务器中的所有 topic 4、查看 first 主题的详情 5、修改分区数**(注意:分区数只能增加,不能减少)** 6、删除 topic,该操作在winodw,会出现文件授权问题,日志可以在kafka的启动命令窗口中查看,

    2024年02月10日
    浏览(48)