java 计时器怎么用 java实现定时器的方式

Java在1.3版本中引入了定时器工具类,这是一个古老的定时器,与TimerTask和TaskQueue一起使用。从Java5开始,另一个计时器Scheduledthreadpoolexecutor被引入到并行契约中。它对Timer做了很多改进,提供了更多的工具,可以考虑作为Timer的替代品。那为什么要引入定时器工具类...

Java在1.3版本中引入了定时器工具类,这是一个古老的定时器,与TimerTask和TaskQueue一起使用。从Java5开始,另一个计时器
Scheduledthreadpoolexecutor被引入到并行契约中。它对Timer做了很多改进,提供了更多的工具,可以考虑作为Timer的替代品。

那为什么要引入定时器工具类呢?了解Timer的功能及其背后的原理,有助于我们更好地理解
ScheduledThreadPoolExecutor。同时scheduledthreadpoolexecutor的一些改进思路也可以在我们平时的编码工作中借鉴。

主要成员变量

计时器中主要使用两个成员变量:

TaskQueue:一个按照

时间

优先排序的队列,这里的

时间

是每个定时任务下一次执行的毫秒数(相对于1970年1月1日而言)TimerThread:对TaskQueue里面的定时任务进行编排和触发执行,它是一个内部无限循环的线程。//根据时间进行优先排序的队列 private final TaskQueue queue = new TaskQueue();//消费线程,对queue中的定时任务进行编排和执行private final TimerThread thread = new TimerThread(queue);//构造函数public Timer(String name) { thread.setName(name); thread.start();}

计时功能

定时器提供三种计时模式:

一次性任务按照固定的延迟执行(fixed delay)按照固定的周期执行(fixed rate)

第一种很好理解,就是任务只执行一次;对于第一种,Timer提供了以下两种方法:

//在当前时间往后delay个毫秒开始执行public void schedule(TimerTask task, long delay) {...}//在指定的time时间点执行public void schedule(TimerTask task, Date time) {...}

第二种

固定延迟模式

也提供了以下两种方法

//从当前时间开始delay个毫秒数开始定期执行,周期是period个毫秒数public void schedule(TimerTask task, long delay, long period) {...}////从指定的firstTime开始定期执行,往后每次执行的周期是period个毫秒数public void schedule(TimerTask task, Date firstTime, long period){...}

它的工作方式是:

第一次执行时间将按照指定的时间点执行(如果TimerThread此时没有执行其他任务)。如果正在执行其他任务,则必须等到其他任务完成。

从第二次开始,每个任务的执行时间是最后一个任务开始执行的时间加上指定的时间段毫秒。

怎么理解呢?还是看代码吧。

public static void ***in(String[] args) { TimerTask task1 = new DemoTimerTask("Task1"); TimerTask task2 = new DemoTimerTask("Task2"); Timer timer = new Timer(); timer.schedule(task1, 1000, 5000); timer.schedule(task2, 1000, 5000);} static class DemoTimerTask extends TimerTask { private String taskName; private DateFor***t df = new SimpleDateFor***t("HH:mm:ss---"); public DemoTimerTask(String taskName) { this.taskName = taskName; } @Override public void run() { System.out.println(df.for***t(new Date()) + taskName + " is working."); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(df.for***t(new Date()) + taskName + " finished work."); }}

Task1和task2是几乎同时执行的两个任务,执行时间为2秒。如果此时不执行第六行,会得到如下结果(与第三种固定费率模式相同):

13:42:58---Task1 is working.13:43:00---Task1 finished work.13:43:03---Task1 is working.13:43:05---Task1 finished work.13:43:08---Task1 is working.13:43:10---Task1 finished work.

如果你打开第六行,我们来看看接下来两个任务的执行情况。我们期望两个任务同时执行,但是Task2是在Task1完成后才执行的(原因是TimerThread是单线程的,每个调度任务的执行也是在这个线程内完成的。当需要同时执行多个任务时,只能阻塞),导致Task2第二次执行(13:43:57)加5秒(13: 44: 57)

13:43:55---Task1 is working.13:43:57---Task1 finished work.13:43:57---Task2 is working.13:43:59---Task2 finished work.13:44:00---Task1 is working.13:44:02---Task1 finished work.13:44:02---Task2 is working.13:44:04---Task2 finished work.

如果在同一时间和间隔内执行另一个Task3会怎么样?

结论:也会依次排队,执行时间取决于两个因素:

1.上次执行时间

2.在预期的时间点是否有其他任务正在执行?如果有,只能排队了。

再来看看第三种

固定费率模式

。我们稍微修改了一下上面的代码:

public static void ***in(String[] args) { TimerTask task1 = new DemoTimerTask("Task1"); TimerTask task2 = new DemoTimerTask("Task2"); Timer timer = new Timer(); timer.scheduleAtFixedRate(task1, 1000, 5000); timer.scheduleAtFixedRate(task2, 1000, 5000);} static class DemoTimerTask extends TimerTask { private String taskName; private DateFor***t df = new SimpleDateFor***t("HH:mm:ss---"); public DemoTimerTask(String taskName) { this.taskName = taskName; } @Override public void run() { System.out.println(df.for***t(new Date()) + taskName + " is working."); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(df.for***t(new Date()) + taskName + " finished work."); }}

Task1和Task2仍然在同一时间按照相同的周期执行任务。我们期望Task1每隔5秒定期执行任务。预计时间为:14:21:47-14:21:52-14:21:57-14:22:02-14:22:07。其实是可以交替的。

14:21:47---Task1 is working.14:21:49---Task1 finished work.14:21:49---Task2 is working.14:21:51---Task2 finished work.14:21:52---Task2 is working.14:21:54---Task2 finished work.14:21:54---Task1 is working.14:21:56---Task1 finished work.14:21:57---Task1 is working.14:21:59---Task1 finished work.14:21:59---Task2 is working.14:22:01---Task2 finished work.

定时器线程

上面我们主要讲了Timer的一些主要源代码和计时方式。下面我们来分析一下支持Timer的计时任务线程TimerThread。

TimerThread大概流程图如下:

定时器线程的大致流程图如下:

定时器线程过程

源代码解释如下:

private void ***inLoop() { while (true) { try { TimerTask task; boolean taskFired; synchronized(queue) { // 如果queue里面没有要执行的任务,则挂起TimerThread线程 while (queue.isEmpty() && newTasksMayBeScheduled) queue.wait(); // 如果TimerThread被激活,queue里面还是没有任务,则介绍该线程的无限循环,不再接受新任务 if (queue.isEmpty()) break; long currentTime, executionTime; // 获取queue队列里面下一个要执行的任务(根据时间排序,也就是接下来最近要执行的任务) task = queue.getMin(); synchronized(task.lock) { if (task.state == TimerTask.CANCELLED) { queue.removeMin(); continue; // No action required, poll queue again } currentTime = System.currentTimeMillis(); executionTime = task.nextExecutionTime; // taskFired表示是否需要立刻执行线程,当task的下次执行时间到达当前时间点时为true if (taskFired = (executionTime<=currentTime)) { //task.period==0表示这个任务只需要执行一次,这里就从queue里面删掉了 if (task.period == 0) { queue.removeMin(); task.state = TimerTask.EXECUTED; } else { // Repeating task, reschedule //针对task.period不等于0的任务,则计算它的下次执行时间点 //task.period<0表示是fixed delay模式的任务 //task.period>0表示是fixed rate模式的任务 queue.rescheduleMin( task.period<0 ? currentTime - task.period : executionTime + task.period); } } } // 如果任务的下次执行时间还没有到达,则挂起TimerThread线程executionTime - currentTime毫秒数,到达执行时间点再自动激活 if (!taskFired) queue.wait(executionTime - currentTime); } // 如果任务的下次执行时间到了,则执行任务 // 注意:这里任务执行没有另起线程,还是在TimerThread线程执行的,所以当有任务在同时执行时会出现阻塞 if (taskFired) // 这里没有try catch异常,当TimerTask抛出异常会导致整个TimerThread跳出循环,从而导致Timer失效 task.run(); } catch(InterruptedException e) { } }}

结论

通过以上分析,我们可以得出以下结论:

Timer支持三种模式的定时任务(一次性任务,Fixed Delay模式,Fixed Rate模式)Timer中的TimerThread是单线程模式,因此导致所有定时任务不能同时执行,可能会出现延迟TimerThread中并没有处理好任务的异常,因此每个TimerTask的实现必须自己try catch防止异常抛出,导致Timer整体失效

演示代码位置

本文来自不择手段投稿,不代表舒华文档立场,如若转载,请注明出处:https://www.chinashuhua.cn/24/596713.html

打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
() 0
上一篇 06-18
下一篇 06-18

相关推荐

  • 定时群发软件 计时器app推荐

    WinExit中文绿色版一款简单方便的电脑计时助手软件,绿色环保,免安装。您可以设置电脑在指定时间关机、重启、睡眠和休眠。有时我们需要等待下载或其他操作,但我们不需要有人照看。这时候定时关机是很有效的。可以设置任务完成后半小时自动关机,或者更久,这样就不用在电脑

    2023-07-24 19:18:01
    168 0
  • 计时器锁屏显示 锁屏时钟插件

    如果你经常使用秒表或计时器,你可能会喜欢新版的Simple Timer,这是iOS开发者NeinZedd9推出的一款全新插件。它允许用户直接使用锁屏界面中的秒表或计时器功能。通常,iPhone用户需要进入时钟应用程序或控制中心才能使用秒表或计时器功能。安装简单定时器后,用户只需简单的手

    2023-07-21 19:52:01
    575 0
  • 我的世界计时器教程 详细制作教程分享

    不知道冒险者在玩一些解密和跑酷地图的时候有没有遇到一些定时关卡。如果玩家不能按时完成关卡内容,将会受到相应的惩罚。为了达到这种效果,那么定时器是必不可少的。今天,魔方菌将带冒险者们学习一些关于红石计时器的小知识。接下来,我们一起来康康吧!先考验一下冒险者吧

    2023-06-25 06:34:01
    559 0
  • java 计时器怎么用 java实现定时器的方式

    Java在1.3版本中引入了定时器工具类,这是一个古老的定时器,与TimerTask和TaskQueue一起使用。从Java5开始,另一个计时器Scheduledthreadpoolexecutor被引入到并行契约中。它对Timer做了很多改进,提供了更多的工具,可以考虑作为Timer的替代品。那为什么要引入定时器工具类

    2023-06-18 12:04:01
    728 0

评论列表

联系我们

在线咨询: QQ交谈

邮件:admin@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信