java多线程编程核心技术——第五章总结

定时器Timer的使用

  在JDK中Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务。

  Timer类的主要作用是设置计划任务,但封装任务的类却是TimerTask类。

  执行计划任务的代码要放入TimerTask的子类中,因为TimerTask是一个抽象类。

  注:在做Demo期间阿里的IDEA插件爆出建议:

  多线程并发处理定时任务时,Timer运行多个TimerTask时,只要其中之一没有捕获抛出的异常,其它任务就会终止,使用ScheduledExecutorService则没有这个问题。

方法schedule(TimerTask task, Date time)的测试

 1.执行任务的时间晚于当前时间:在未来执行的效果。

Timer timer = new Timer();

   这个构造是获取Timer对象的方式直接,这个构造方法创建的是非守护线程。

   TimerTask类似于线程(但并不是),他所执行的的定时任务是重写在run()方法中的(自定义任务类继承TimerTask然后重写了run())。

class MyTask extends TimerTask {
  public void run(){}
}
MyTask task = new MyTask();
//通过下面方法实现执行定时任务,date为要执行run()的时间。
timer.schedule(task,date)

  只要将date设置为未来的时间,且重写run()方法,就可以在制定时间执行想要做的定时任务了。

  这个Timer的构造是创建的是一个守护线程。

Timer timer = new Timer(true);

  源码如下:

  这个空参构造最终会调用下面的构造

  可以看出空参构造的作用:创建一个Timer就是启动一个新的线程,而且这个新线程并不是守护线程一直运行。

  使用另一种构造,则可以获取守护线程:

2.计划时间早于当前时间,提前运行的效果

  注:如果执行任务的时间早于当前时间,那么立即执行task任务。

3.多个TimerTask任务及延时的测试

  多个TimerTask可以被一个Timer执行。调用的方法是:schedule(TimerTask task, Date time)。

  TimerTask是以队列的方式一个一个被顺序执行的,所以可能出现执行的时间与预期的时间不一致的情况,因为前面的任务有可能消耗较长的时间,则后面的任务会被延迟。

方法schedule(TimerTask task, Date firstTime, long period)的测试

  该方法是在指定的日期后(firstTime)按指定的间隔(period)周期性地无限地执行某一任务。

1.计划时间晚于当前时间:在未来执行的结果

  一旦当前时间(本地计算机时间)到达指定时间(firstTime),TimerTask中的任务会被立即执行,随后每间隔一段时间(period)执行一次。

2.计划时间早于当前时间:提前运行的效果 

  在当前时间立即执行TimerTask中的任务,且每个一段时间(period)执行一次。

  注:起点以当前线程启动的时间为准,即调用schedule()方法为准,间隔也是以这个时间为起点。

3.任务执行时间被延时

  如果程序执行的消耗时间大于间隔时间(period),那么任务的执行就会延后,谁大以谁为准。

  注:消耗时间大,就以消耗时间为准;间隔时间大,就以间隔时间为准。

4.TimerTask类的cancel()方法  

  TimerTask类的cancle()方法是将自身从任务队列中移除,其他任务依旧在任务队列不收影响。

5.Timer类的cancel()方法

  Timer类的cancel()方法作用是将任务队列中的全部任务清空。

  注:调用cancel()后,全部任务被清空,进程被销毁。

  注:Timer类的cancel()的注意事项:Timer类中的cancel()方法有时并不一定会停止执行计划任务,而是正常执行。

    这是因为Timer类中的cancel()方法有时并没有争抢到queue锁,所以TimerTask类中的任务继续正常执行。

    (这个注意事项,我没有想太明白,以后会再看的)

方法schedule(TimerTask task, long delay)的测试

  该方法的作用是以当前时间为参考时间(这个当前时间指的是调用schedule(TimerTask task,long delay)的时间),在此基础上延迟指定毫秒数后执行一次TimerTask任务。 

方法schedule(TimerTask task, long delay, long period)的测试

  该方法的作用是以当前时间为参考时间(这个当前时间指的是调用schedule(TimerTask task,long delay)的时间),在此基础上延迟指定毫秒数,再以某一间隔时间无限次地执行某一任务。

方法scheduleAtFixedRate(TimerTask task, Date firstTime, long period)的测试

  方法schedule与方法scheduleAtFixedRate都会按顺序执行,所以不需要考虑非线程安全的情况。

  方法schedule与方法scheduleAtFixedRate的主要区别在于不延时的情况。

  使用schedule方法,如果执行任务没有被延时,那么下一次任务的执行时间参考的是上一次任务的“开始”时的时间计算的。

  使用scheduleAtFixedRate方法,如果执行任务没有被延时,那么下一次任务的执行时间参考的是上一次任务的“结束”的时间计算的。

  延时的情况则没有区别,也就是说如果两者都被延时,那么都已上一次任务结束的时间计算。

注:schedule不具有追赶性。

  scheduleAtFixedRate具有追赶性。

  追赶性:起始时间早于当前时间,会将两段时间内的任务进行追赶式(弥补错过的时间)的执行。

  这只是定时器简单的API实现。

  实际上Spring通过了注解实现定时器,会找时间对其进行总结的。

  注解式定时器——SpringTask的实现(未完成)

本文内容是书中内容兼具自己的个人看法所成。可能在个人看法上会有诸多问题(毕竟知识量有限,导致认知也有限),如果读者觉得有问题请大胆提出,我们可以相互交流、相互学习,欢迎你们的到来,心成意足,等待您的评价。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java帮帮-微信公众号-技术文章全总结

【大牛经验】关于堆和栈的那些事

问题描述 编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么。我仅有高级语言编程经验,没有看过对此更清晰的解释。...

3459
来自专栏jouypub

MySQL查询语句优化

在项目中经常和MySQL数据库打交道,写过各种各样的SQL,也遇到过各种问题,针对遇到的各种场景,记录一些解决方案,主要是MySQL索引问题。

110
来自专栏Golang语言社区

论golang是世界上最好的语言

概述 golang is a better C and a simple C++ golang主要特性 1、语法简单 舍弃语法糖,严格控制关键字 C++语法糖之...

3579
来自专栏后端技术探索

什么是堆和栈,它们在哪儿?

编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么。我仅有高级语言编程经验,没有看过对此更清晰的解释。我的意思是...

882
来自专栏IT技术精选文摘

Java并发包类总览

并发容器 这些容器的关键方法大部分都实现了线程安全的功能,却不使用同步关键字(synchronized)。值得注意的是Queue接口本身定义的几个常用方法的区...

18310
来自专栏一名叫大蕉的程序员

大数据计数原理1+0=1这你都不会算(五)No.55

Hello哈,又好久没聊大数据相关的东西了,是不是又忘记了吖?这次聊聊B-树的升级版,B+树。前面的内容小伙伴可以回顾一下。 大数据计数原理1+0=1这你都不...

1839
来自专栏无题

读《Effecttive Java》

“读完一本《Effecttive Java》,才算是一个中级Java程序员” 2019-09-15 “读完一本《Effecttive Java》,才算是一个中...

3465
来自专栏闻道于事

Spring框架(一)

Spring:   Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由 Rod Johnson在其著作 Exper...

3456
来自专栏撸码那些事

【抽象那些事】命令式抽象

1173
来自专栏杨建荣的学习笔记

索引列顺序导致的性能问题

今天和大家分享一个很有意思的例子,关于索引列的顺序导致的性能问题。 发现数据库的性能比较差,CPU消耗很高,抓了一个awr,发现瓶颈在sql上,top 1的sq...

3505

扫码关注云+社区