传统线程技术中有个定时器,定时器的类是Timer,我们使用定时器的目的就是给它安排任务,让它在指定的时间完成任务。所以先来看一下Timer类中的方法(主要看常用的TimerTask()方法):

前面两个是在指定延迟后执行或者重复执行,后面两个是在指定时间执行或者重复执行。我们以前两个为例来研究一下定时器的使用。
先写一个简单的使用定时器的demo,然后慢慢引申。

public class TraditionalTimer {public static void main(String[] args) {//简单定时器的demonew Timer().schedule(new TimerTask() {          @Overridepublic void run() {//实际中会扔一个对象进来,我们就可以在这里操作这个对象的所有方法了System.out.println("--boom--");//爆炸}}, 2000,3000); //打印秒钟,一秒输出一次,用来方便观察的while(true) {System.out.println(new Date().getSeconds());try {Thread.sleep(1000);} catch(Exception e) {e.printStackTrace();}}}
}

我们用匿名内部类来定义了一个TimerTask对象,需要重写run()方法,然后运行这个程序,可以看出来第一次2秒钟后打印“--boom--,后面每隔3秒打印一次。
我们也可以自己来实现上面这个重复执行,我们用定时器的“连环套”!也就是定时器中再套定时器,一个定时器任务执行完了,在任务的最后再装一个定时器。那么我们需要先定义一个自己的定时器任务,在自己的定时器任务中再装一个定时器,把自定义的定时器任务扔进去。然后我们开启定时器的时候把自己定义的定时器任务扔进去即可。如下:

public class TraditionalTimer {public static void main(String[] args) {//自定义一个定时器任务class MyTimerTask extends TimerTask {           @Overridepublic void run() {System.out.println("--boom--");//任务执行完再装一个定时器,扔进自定义的定时器任务new Timer().schedule(new MyTimerTask(), 3000);}}new Timer().schedule(new MyTimerTask(), 2000);//外面开启定时器while(true) {//打印秒钟,一秒输出一次System.out.println(new Date().getSeconds());try {Thread.sleep(1000);} catch(Exception e) {e.printStackTrace();}}}
}

这样的话,我们通过定时器的“连环套”很轻松的实现了连环爆炸。但是现在问题来了,上面提供的方法中重复执行都是每隔固定的时间,如果我想要隔2秒执行一次,再隔4秒执行一次,再隔2秒执行一次,再隔4秒执行一次……这该如何实现呢?
可以这样,我们定义一个全局的私有成员变量来记录爆炸次数,奇数的时候隔2秒炸,偶数的次数的话隔4秒炸,或者反过来也行,修改如下:

public class TraditionalTimer {private static int count = 0; //记录爆炸的次数public static void main(String[] args) {    class MyTimerTask extends TimerTask {           @Overridepublic void run() {count = (count + 1) % 2; //结果只有0和1System.out.println("--boom--");new Timer().schedule(new MyTimerTask(), 2000+2000*count);//根据count结果设定新的定时时间}}new Timer().schedule(new MyTimerTask(), 2000);while(true) {//打印秒钟,一秒输出一次System.out.println(new Date().getSeconds());try {Thread.sleep(1000);} catch(Exception e) {e.printStackTrace();}}}
}

这样的话,我们就实现了自定义爆炸间隔了。上面这个是通过定义一个全局私有变量来实现,其实我们也可以这么干:不是要实现两个不同时间间隔的连环炸么?我可以定义两个定时器任务A和B,在A执行完开启定时器,把B任务装进去,B执行完开启定时器把A装进去,这样也可以。如下:

public class TraditionalTimer {public static void main(String[] args) {new Timer().schedule(new MyTimerTaskA(), 2000);//A和B随便开一个while(true) {//打印秒钟,一秒输出一次System.out.println(new Date().getSeconds());try {Thread.sleep(1000);} catch(Exception e) {e.printStackTrace();}}}}
//自定义两个定时器任务类,继承TimerTask即可
class MyTimerTaskA extends TimerTask {@Overridepublic void run() {System.out.println("--boomA--");new Timer().schedule(new MyTimerTaskB(), 4000);}
}
class MyTimerTaskB extends TimerTask {@Overridepublic void run() {System.out.println("--boomB--");new Timer().schedule(new MyTimerTaskA(), 2000);}
}

这样就可以实现自定义时间间隔的连环炸了。传统的定时器技术就总结这么多吧~
更多优质文章和资源,请关注公众号:【程序员私房菜】。

转载于:https://www.cnblogs.com/eson15/p/9824647.html

Java并发基础02. 传统线程技术中的定时器技术相关推荐

  1. Java并发基础01. 传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...

  2. Java并发编程(02):线程核心机制,基础概念扩展

    本文源码:GitHub·点这里 || GitEE·点这里 一.线程基本机制 1.概念描述 并发编程的特点是:可以将程序划分为多个分离且独立运行的任务,通过线程来驱动这些独立的任务执行,从而提升整体的效 ...

  3. java 线程假醒_Java并发基础05. 传统线程同步通信技术

    先看一个问题: 有两个线程,子线程先执行10次,然后主线程执行5次,然后再切换到子线程执行10,再主线程执行5次--如此往返执行50次. 看完这个问题,很明显要用到线程间的通信了, 先分析一下思路:首 ...

  4. Java并发基础(六) - 线程池

    Java并发基础(六) - 线程池 1. 概述 这里讲一下Java并发编程的线程池的原理及其实现 2. 线程池的基本用法 2.1 线程池的处理流程图 该图来自<Java并发编程的艺术>: ...

  5. java线程抢占式执行,Java并发基础(一)-线程基础

    原标题:Java并发基础(一)-线程基础 只要涉及到线程,其运行结果就是不确定的,虽然说java很早就提供了线程以及并发的支持,但是我们需要知道,线程是完全交给调度器的.有很多同学在编写书上的代码时, ...

  6. 【Java进阶】Java并发类库提供的线程池有哪几种? 分别有什么特点?

    我在专栏第 17 讲中介绍过线程是不能够重复启动的,创建或销毁线程存在一定的开销,所以利用线程池技术来提高系统资源利用效率,并简化线程管理,已经是非常成熟的选择. 今天我要问你的问题是,Java 并发 ...

  7. java并发编程实践(2)线程安全性

    [0]README 0.0)本文部分文字描述转自:"java并发编程实战", 旨在学习"java并发编程实践(2)线程安全性" 的相关知识: 0.1)几个术语( ...

  8. Java 并发 多线程:创建线程的四种方式

    Java 并发 多线程: 创建线程的四种方式 继承 Thread 类并重写 run 方法 实现 Runnable 接口 实现 Callable 接口 使用线程池的方式创建 1. 通过继承 Thread ...

  9. Java并发(五)线程池使用番外-分析RejectedExecutionException异常

    Java并发(五)线程池使用番外-分析RejectedExecutionException异常 参考文章: (1)Java并发(五)线程池使用番外-分析RejectedExecutionExcepti ...

最新文章

  1. 如何找到存在Ceph里面的文件
  2. android 上键,在Android键盘上设置Return键
  3. zbrush 添加纹理贴图_zbrush零基础新手必看入门讲解
  4. Nodejs是什么?
  5. java 支付宝wap支付初识
  6. C语言:判断三角形是否为直角三角形
  7. 在pcDuino上安装OpenJFX
  8. WIN7上安装OFFICE 2019(未成功)
  9. 2017网易校招:Fibonacci数列
  10. 51单片机usb烧录电路_51单片机怎么用usb烧写程序
  11. python matplotlib contour画等高线图
  12. AMD首款5纳米PC处理器锐龙7000亮相,频率首破5GHz大关,单核性能提升15%
  13. 计算机项目教学法探讨,基于项目教学法的非计算机专业计算机教学的设计和探讨...
  14. 计算MD5值有几种方式
  15. html5 bdi 不起作用,html bdi标签的使用详解
  16. ETH持续暴雷!历史是如此的相似
  17. 星际2亚洲服务器 也就是韩服
  18. 关于VS编译跨端工程出现error C2059的一个解决方案
  19. 大一大学计算机导论论文,大学计算机导论论文3500字_大学计算机导论毕业论文范文模板.doc...
  20. mysql替换空行解决导出到excel时由于内容有换行回车导致的问题

热门文章

  1. c++ 8.整数加法实现
  2. [BUUCTF-pwn]——jarvisoj_level2_x64
  3. 关于定义视频播放器的界面的相关的类transPortcontroll等
  4. 为什么要进行透明计算和透明计算是什么
  5. linux java 安装 gi_gi的安装和使用
  6. MongoDB分布式操作——分片操作
  7. java BIO NIO AIO 理论篇
  8. JAVA学习:maven开发环境快速搭建How to download J2EE API (javaee.jar) from Maven
  9. scanf的拓展用法——匹配特定字符
  10. 用Macbook开发桌面应用,使用Alamofire链接.Net Core Webapi的注意事项!