,,java 定时器线程池(ScheduledThreadPoolExecutor)的实现

,,java 定时器线程池(ScheduledThreadPoolExecutor)的实现

本文主要介绍java定时器线程池(ScheduledThreadPoolExecutor),通过示例代码非常详细的介绍,对大家的学习或者工作有一定的参考价值。需要的朋友可以和边肖一起学习。

前言

计时器池提供了定期执行任务的能力,也就是说,它可以被延迟或定期执行。但是定时器线程池还是线程池,最底层的实现是ThreadPoolExecutor。可以参考我的另一篇文章《多线程——掌握ThreadPoolExecutor》。

特点说明

1.构造函数

public scheduled threadpoolexecutor(int corePoolSize){

//其他几个参数已经在ThreadPoolExecutor中详细分析过了,这里就不展开了。

//这里可以看到在基类中调用方法时有一个特殊的参数DelayedWorkQueue。

//同时我们也可以发现,这里并没有设置延迟时间、周期等参数。

//所以定时执行的实现必须在DelayedWorkQueue的对象中。

super(corePoolSize,整数。MAX_VALUE,0,纳秒,

new DelayedWorkQueue());

}

2.DelayedWorkQueue

DelayedWorkQueue是ScheduledThreadPoolExecutor中的内部类,它实现BlockingQueue接口。

存储任务队列的数组如下:

private RunnableScheduledFuture?[]队列=

新的RunnableScheduledFuture?[初始容量];

我们分析过ThreadPoolExecutor,它从任务队列中获取任务的方式是poll和take,所以看看poll和take的源代码,回头看,ThreadPoolExecutor会调用poll或take,先poll再take,只要其中一个接口返回。

public RunnableScheduledFuture?poll() {

final reentrant lock lock=this . lock;

lock . lock();

尝试{

RunnableScheduledFuture?first=queue[0];

//这里有一个getDelay,这是重点。获取执行延迟时间。

//但是如果我们有延迟设置,这将返回null,然后调用take方法

if (first==null || first.getDelay(纳秒)0)

返回null

其他

返回finish poll(first);

}最后{

lock . unlock();

}

}

public RunnableScheduledFuture?take()抛出InterruptedException {

final reentrant lock lock=this . lock;

lock . lock interruptible();

尝试{

for(;) {

RunnableScheduledFuture?first=queue[0];

if (first==null)

available . await();

否则{

//获取延迟时间

long delay=first.getDelay(纳秒);

if(延迟=0)

返回finish poll(first);

first=null//等待时不保留ref

如果(领导!=空)

available . await();

否则{

thread this thread=thread . current thread();

leader=thisThread

尝试{

//使用锁,并执行延迟等待。

//使用锁,并执行延迟等待。

//使用锁,并执行延迟等待。

available.awaitNanos(延迟);

}最后{

if (leader==thisThread)

leader=null

}

}

}

}

}最后{

if (leader==null queue[0]!=空)

available . signal();

lock . unlock();

}

}

3.RunnableScheduledFuture

在ScheduledThreadPoolExecutor中,有一个实现RunnableScheduledFuture的scheduledfutuetask类。scheduledfutuetask类采用了decorator设计模式,并在Runnable方法的基础上执行了一些附加功能。

我们需要特别注意几个参数,周期和时间。

(1)时间

先看时间的作用,可以看到时间是用来获取执行延迟时间的,也就是延迟是根据时间产生的。

公共long getDelay(时间单位单位){

return unit.convert(time - now()、纳秒);

}

(2)周期

这个参数不是说设置多少个执行周期,而是确定是否需要按周期执行,以及执行周期,即当前执行与下一次执行之间的时间。

//确定是否需要循环执行。如果循环设置为0,则不会无间隔执行,而只会执行一次。这需要特别注意。

public boolean isPeriodic() {

退货期!=0;

}

私有void setNextRunTime() {

长p=周期;

如果(第0页)

//这里把周期加到时间上,这样得到的延迟时间就是周期时间。

时间=p;

其他

time=trigger time(-p);

}

(3)执行

公共无效运行(){

//先确定是否是周期性任务。

布尔周期=is periodic();

如果(!canRunInCurrentRunState(定期))

取消(假);

else if(!定期)

//如果不是周期性的,执行调用父类的run方法,也就是构造函数中传递的Runnable对象的run方法。

scheduledfuturetask . super . run();

//任务首先在if的括号中执行

else if(scheduledfuturetask . super . runandreset()){

//如果是周期性的,就需要设置下一次执行时间,然后用reExecutePeriodic方法把任务再次扔进任务队列。

//这里特别需要注意的是,if中的逻辑执行失败。如果没有捕获到异常,那么下面的逻辑将不会再次执行。也就是说,一旦中间执行失败,后面的周期性任务就会失败。

setNextRunTime();

re execute periodic(outer task);

}

}

摘要

ScheduledThreadPoolExecutor通过time参数设置当前任务执行的等待时间,然后通过period设置下一次任务执行的等待时间。这两个参数不是在线程池中设置,而是在任务中携带,可以将线程池与任务完全解耦。

注意:

(1)任务的执行等待时间在队列的take方法中。

(2)当2)period参数设置为0时,任务将只执行一次,而不是多次。

(3)如果要自己实现周期性任务,一定要注意在周期性任务执行过程中捕捉异常,否则一次执行失败会导致后续任务周期失败,任务无法继续执行。

关于java定时器线程池(ScheduledThreadPoolExecutor)的实现,本文到此结束。有关java定时器线程池的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望大家以后能多多支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • vue中的定时器清不掉,vue设置定时器调用方法,vue如何设置定时器和清理定时器
  • js定时方法,js的定时器函数
  • js定时方法,js的定时器函数,js定时器的使用(实例讲解)
  • js定时器重复执行怎么停止,js每隔几秒执行一次
  • js定时器重复执行怎么停止,js每隔几秒执行一次,js定时器(执行一次、重复执行)
  • js定时器重复执行怎么停止,,js定时器(执行一次、重复执行)
  • js中2种定时器的使用及清除的实现过程,js中两种定时器的设置及清除
  • js中2种定时器的使用及清除的实现过程,js中两种定时器的设置及清除,JS中2种定时器的使用及清除的实现
  • ,,Qt定时器和随机数详解
  • ,,Qt基础开发之Qt多线程类QThread与Qt定时器类QTimer的详细方法与实例
  • ,,IOS 中NSTimer定时器的使用
  • C语言定时器,c语言定时器程序编写
  • C语言定时器,c语言定时器程序编写,C语言实现简单的定时器
  • java 定时器的多种实现方式有哪些,java定时器的实现方式有几种
  • java 定时器的多种实现方式有哪些,java定时器的实现方式有几种,Java 定时器的多种实现方式
  • 留言与评论(共有 条评论)
       
    验证码: