ScheduledExecutorService:多线程任务调度

简介: ScheduledExecutorService:多线程任务调度

今天使用Timer实现任务调度时,阿里巴巴Java开发规范提示

  • 多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。
  • 建议多线程-任务调度,使用如下方式:
  • 首先引入commons.lang3的jar包
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
   <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>



    //org.apache.commons.lang3.concurrent.BasicThreadFactory
    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
        new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
    executorService.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            //do something
        }
    },initialDelay,period, TimeUnit.HOURS);

具体原因:


  1. Timer不支持多线程。全部挂在Timer下的任务都是单线程的,任务仅仅能串行运行。假设当中一个任务运行时间过长。会影响到其它任务的运行,然后就可能会有各种接踵而来的问题。
  2. Timer的线程不捕获异常。TimerTask假设抛出异常,那么Timer唯一的进程就会挂掉,这样挂在Timer下的全部任务都会无法继续运行。

 

  • 第一个问题,随着业务数据的猛增,我们生产上有几个任务如今每次运行须要1-3个小时。在这段时间内,该timer下的其它任务仅仅能等待,这是让人无法忍受的。重开一个Timer?难道要为全部的耗时的Task都单开一个Timer。显然是不太可能。这样就太乱了。
  • 第二个问题。是极其致命的。
  • 好多业务数据都是晚上的定时任务跑出来的。结果因为程序的问题或者内存资源不足,导致线程被kill了。该timer下的全部任务都未运行。结果第二天整整忙活了一天,主要任务就是——跑任务,调整数据。深受其害呀!
  • 为了弥补Timer的缺陷,jdk1.5中引入了并发包。这里面提供的ScheduledExecutorService。详细实现类是:ScheduledThreadPoolExecutor。ScheduledThreadPoolExecutor支持多线程。同一时候在线程中对异常进行了捕获。所以是Timer的完美替换者。


ScheduledExecutorService方法讲解

 

图片.png

 

public ScheduledFuture<?> schedule(Runnable command,long delay,TimeUnit unit);

用来创建延迟指定时间后执行某个任务的操作,一次性执行任务,执行完成后结束。
command:等待被执行的任务 
delay:任务执行延迟时间
unit:时间单位


public <V> ScheduledFuture<V> schedule(Callable<V> callable,long delay, TimeUnit unit);

创建并执行在给定延迟后启用的 ScheduledFuture。
callable:等待被执行的任务 (这个任务,有返回值并且可以抛出异常)
delay:任务执行延迟时间
unit:时间单位

 

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay,long period,TimeUnit unit);

用来创建并执行一个延迟指定初始化时间的任务操作,周期性执行;在initialDelay后首次执行,然后initialDelay+period,initialDelay+2*period,以此类推。如果任务执行的时间小于period,则按照上面的规则执行任务,反之,任务顺延,以任务实际执行的时间来进行周期执行。
command:等待被执行的任务
initialDelay:任务初始延迟执行时间
period:任务执行间隔周期
unit:时间单位

 

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay, long delay,TimeUnit unit);

用来创建并执行一个延迟指定初始化时间的任务操作,周期性执行;在initialDelay后首次执行,然后每一次执行终止和下一次的任务执行开始之间都存在delay的时间延迟,如果任务的执行时间超过延迟时间delay,则下一个任务会在任务执行时间+delay后执行
command:等待被执行的任务
initialDelay:任务初始延迟执行时间
delay:延迟时间
unit:时间单位

 

scheduleAtFixedRate和scheduleWithFixedDelay对比


  • 方法参数是一样的。第一个参数是任务实例,第二个参数是延迟时间,第三个是间隔时间,第四个是时间单元。
  • 这两个方法的不同之处在方法名也能看得出来:scheduleAtFixedRate方法是按照固定频率去执行任务的。而scheduleWithFixedDelay方法则是按照固定的延迟去执行任务。
  • ScheduleAtFixedRate每次执行时间为上一次任务开始起向后推一个时间间隔,即每次执行时间为initialDelay,initialDelay+period,initialDelay+2*period。。。。。
  • ScheduleWithFixedDelay每次执行时间为上一次任务结束起向后推一个时间间隔,即每次执行时间为:initialDelay,initialDelay+executeTime+delay,initialDelay+2*executeTime+2*delay。。。。。
  • 由此可见,ScheduleAtFixedRate是基于固定时间间隔进行任务调度,ScheduleWithFixedDelay取决于每次任务执行的时间长短,是基于不固定时间间隔进行任务调度。


参考来源:https://www.cnblogs.com/jzssuanfa/p/6958957.html


目录
相关文章
|
算法 Java Go
【多线程系列-03】深入理解java中线程的生命周期,任务调度
【多线程系列-03】深入理解java中线程的生命周期,任务调度
193 0
|
9月前
|
缓存 监控 Java
Java并发编程:线程池与任务调度
【4月更文挑战第16天】Java并发编程中,线程池和任务调度是核心概念,能提升系统性能和响应速度。线程池通过重用线程减少创建销毁开销,如`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。任务调度允许立即或延迟执行任务,具有灵活性。最佳实践包括合理配置线程池大小、避免过度使用线程、及时关闭线程池和处理异常。掌握这些能有效管理并发任务,避免性能瓶颈。
77 0
|
Java 调度
任务调度线程池
任务调度线程池
|
缓存 Java 调度
【Android 异步操作】线程池 ( 线程池作用 | 线程池种类 | 线程池工作机制 | 线程池任务调度源码解析 )
【Android 异步操作】线程池 ( 线程池作用 | 线程池种类 | 线程池工作机制 | 线程池任务调度源码解析 )
149 0
|
调度
任务调度(四)——ScheduledExecutorService替代Timer,实现多线程任务调度
       上篇博文《任务调度(三)——Timer的替代品ScheduledExecutorService简介》已经对ScheduledExecutorService做了简单介绍,其实使用ScheduledExecutorService来替代Timer也是迫不得已的事情。
1260 0
|
并行计算 调度 编译器
OpenMP 中的线程任务调度
OpenMP中任务调度主要针对并行的for循环,当循环中每次迭代的计算量不相等时,如果简单地给各个线程分配相同次数的迭代,则可能会造成各个线程计算负载的不平衡,影响程序的整体性能。 如下面的代码中,如果每个线程执行的任务数量平均分配,有的线程会结束早,有的线程结束晚: 1 #include...
1382 0
|
3天前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
32 20
|
9天前
|
安全 Java C#
Unity多线程使用(线程池)
在C#中使用线程池需引用`System.Threading`。创建单个线程时,务必在Unity程序停止前关闭线程(如使用`Thread.Abort()`),否则可能导致崩溃。示例代码展示了如何创建和管理线程,确保在线程中执行任务并在主线程中处理结果。完整代码包括线程池队列、主线程检查及线程安全的操作队列管理,确保多线程操作的稳定性和安全性。
|
2月前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
79 1
|
4月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
79 1