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

Java在1.3版本引入了Timer工具类,它是一个古老的定时器,搭配TimerTask和TaskQueue一起使用。从Java5开始在并发包中引入了另一个定时器ScheduledThreadPoolExecutor,它对Timer做了很多改进并提供了更多的工具,可以认为是对Timer的取代。 那为什么还要介绍Timer工具类呢?通过了解Timer的功能和它背后的原理,有助于我们更好的对比了解Sc…

Java在1.3版本号引入了Timerjava工具,它是一个历史悠久的计时器,配搭TimerTask和TaskQueue一起应用。从Java5逐渐在并分包中引入了另一个计时器
ScheduledThreadPoolExecutor,它对Timer进行了许多改善并带来了大量的专用工具,可以觉得是对Timer的替代。

那为什么还需要详细介绍Timerjava工具呢?根据掌握Timer的基本功能和它后面的基本原理,有利于大家更快的比照掌握
ScheduledThreadPoolExecutor,与此同时ScheduledThreadPoolExecutor的一些改善观念在大家日常的编号工作中中也可以参考。

关键成员变量

Timer中采用的主要是2个成员变量:

  1. TaskQueue:一个依照時间优先选择排序的序列,这儿的時间是每一个定时任务下一次执行的ms数(相对性于1970年1月1日来讲)
  2. 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();
}

按时作用

Timer给予了三种按时方式:

  1. 一次性每日任务
  2. 依照确定的延迟时间执行(fixed delay)
  3. 依照确定的周期时间执行(fixed rate)

第一种比较好了解,即每日任务只执行一次;对于第一种,Timer给予了下列2个方式:

//在现在时间往后面delay个ms逐渐执行
public void schedule(TimerTask task, long delay) {...}
//在规定的time时间点执行
public void schedule(TimerTask task, Date time) {...}

第二种Fixed Delay方式也给予了下列2个方式

//从现在时间逐渐delay个ms数逐渐按时执行,周期时间是period个ms数
public void schedule(TimerTask task, long delay, long period) {...}
////从特定的firstTime逐渐按时执行,往后面每一次执行的期限是period个ms数
public void schedule(TimerTask task, Date firstTime, long period){...}

它的工作方式是:

第一次执行的时长将根据规定的时间点执行(假如这时TimerThread没有在执行别的每日任务),若有别的每日任务在执行,那么就要直到别的每日任务执行进行才可以执行。

从第二次逐渐,每一次每日任务的执行时间是上一次任务逐渐执行的時间再加上特定的periodms数。

怎样看待呢,大家或是看编码

public static void main(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 DateFormat df = new SimpleDateFormat(\"HH:mm:ss---\");
        public DemoTimerTask(String taskName) {
            this.taskName = taskName;
        }
        @Override
        public void run() {
            System.out.println(df.format(new Date())   taskName   \" is working.\");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(df.format(new Date())   taskName   \" finished work.\");
        }
}

task1和task2是几乎与此同时执行的2个每日任务,并且执行时间全是2秒左右,假如这个时候大家把第六行注掉不执行,我们将获得如下所示結果(和第三种Fixed Rate方式結果同样):

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.

假如开启第六行,大家再看看2个每日任务的执行状况。我们都是期待2个每日任务可以与此同时执行,可是Task2是在Task1执行进行后才逐渐执行(缘故是TimerThread是单核的,每一个定时任务的执行也在该进程内进行,当好几个每日任务与此同时必须执行时,只有是堵塞了),进而造成Task2第二次执行的时间是它上一次执行的時间(13:43:57)再加上5秒左右(13:44:02)。

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也是相同的时间点和间距执行会怎么样?

结果是:也将先后排长队,执行的時间依靠2个要素:

1.之前执行的時间

2.期待执行的时间点上是否有别的每日任务在执行,有则只有排长队了


大家接着看下第三种Fixed Rate方式,大家将里面的编码稍加改动:

public static void main(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 DateFormat df = new SimpleDateFormat(\"HH:mm:ss---\");
        public DemoTimerTask(String taskName) {
            this.taskName = taskName;
        }
        @Override
        public void run() {
            System.out.println(df.format(new Date())   taskName   \" is working.\");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(df.format(new Date())   taskName   \" finished work.\");
        }
}

Task1和Task2或是在同样的时间点,依照同样的周期时间按时执行每日任务,大家期待Task1可以每5秒按时执行每日任务,期待的时间点是:14:21:47-14:21:52-14:21:57-14:22:02-14:22:07,事实上它可以更替着按时执行,缘故是Task2也会按时执行,而且对TaskQueue的锁她们是轮换着拿的(这一在下面剖析TimerThread源代码的过程中会讲到)

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.

TimerThread

上边大家具体讲了Timer的一些关键源码及定期方式,下边大家来剖析下支撑Timer的定时任务线程TimerThread。

TimerThread大概流程表如下所示:Java定时任务之Timer原理解析

TimerThread步骤

源码表述如下所示:

private void mainLoop() {
        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 - currentTimems数,抵达实行时间点再全自动激话
                    if (!taskFired) 
                        queue.wait(executionTime - currentTime);
                }
                // 假如每日任务的下一次实行时间到了,则执行任务
                // 留意:这儿每日任务实行沒有另起线程,或是在TimerThread线程实行的,因此当有每日任务在与此同时实行的时候会发生堵塞
                if (taskFired)  
                    // 这儿沒有try catch出现异常,当TimerTask抛出异常会致使全部TimerThread跳出循环,进而造成Timer无效
                    task.run();
            } catch(InterruptedException e) {
            }
        }
}

结果

根据以上的剖析,我们可以得到下列结果:

  1. Timer适用三种策略的定时任务(一次性每日任务,Fixed Delay方式,Fixed Rate模式)
  2. Timer中的TimerThread是单线程方式,因而造成全部定时任务不可以与此同时实行,很有可能会发生延迟时间
  3. TimerThread中并没解决好每日任务的出现异常,因而每一个TimerTask的建立务必自身try catch避免出现异常抛出去,造成Timer整体失效

Demo编码部位

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

(0)
上一篇 2022年5月11日 上午11:00
下一篇 2022年5月11日 上午11:01

相关推荐

  • 中国第57个民族是什么族,揭秘其久久不被认可的原因

    在近代的中国,我们没有战斗和谐相处,是很多外国人羡慕的地方,都想成为我们中国的后代,拿这些究竟是怎么起源的呢,还要从2003年说起,当时我们中国接纳了一个流浪的民族,把他们纳入中国的范畴,因为中国的自身条件良好,使得他们在心底里把中国当成了他们的梦想的地方。 这个名族就是达曼族,他们在藏族居住,因为他们的名字是以族名为名,所以就取名为达曼村,这个村子很小,总共才47户,一共还不到200人,那达曼在…

    2022年10月9日
    550
  • 有没有免费合并pdf的软件(不需要会员的pdf转换器)

    样将多个PDF文档合并成一个?PDF是我们日常工作使用较多的一种文档格式,有时需要将几份PDF合成一个单独文档使用,应该如何操作呢?是否有一些免费又好用的PDF合并软件可以直接使用? 软件1:极速PDF编辑器 优势:专业的PDF编辑器,合并PDF文档时设置比较详细,满足更多需求。 使用步骤: 1、首先打开极速PDF编辑器后,点击右上角“文件”选项卡中的“合并”; 2、接着弹出的“合并文件”窗口右侧…

    2022年5月9日
    1090
  • 公众号快速吸粉的方式有哪些,公众号线上吸粉活动介绍

    1、手机陌陌留言板,附近人宣传 玩微信的人很多,玩陌陌的人也不少。陌陌被称为约炮神器,年轻人玩的更多。像陌陌的附近人,我们可以关注,打招呼。像陌陌的留言板,我们可以发布留言也可以给他们评论,效果都是非常不错的。当然,我们的陌陌资料也要引导用户去关注我们的公众号。 2、手机微视原创视频,评论宣传 微视,是手机上的一款微视社交软件,以前我总喜欢玩微视,有一些搞笑的,新闻,明星等微视频非常的不错。我们可…

    2022年8月4日
    690
  • 网站优化排名软件有哪些,seo优化必备的5种工具

    2019年哪些工具可以辅助SEO网站优化? 很多公司做优化都想了解哪些工具可以辅助优化?这是每个seo都会遇到的问题,究竟有什么工具可以辅助优化?可以使网站排名更好呢?哪些工具经常能用到呢?下面小编来给大家详细讲解一下。 推荐几个专业SEO网站优化工具? SEO工具就是针对搜索引擎优化的各类工具,比如查询工具、排名工具、流量分析软件、站群软件等,用好各类工具可以节省很多时间,让SEO服务变得更加轻…

    2022年8月18日
    550
  • js样式选择(js追加样式css样式的方法)

    介绍 JSS是CSS的创作工具,它允许你使用JavaScript以声明,无冲突和可重用的方式描述样式。它可以在浏览器,服务器端或在构建时在Node中编译。JSS与框架无关。它由多个包组成:核心部分,插件以及框架集成等。 Github https://github.com/cssinjs/jssstars:5.1k 快速开始 如果你已经对使用JSS感兴趣,可以使用在线代码编辑器。在CodeSandb…

    2022年8月22日
    1840
  • 笔记本哪个牌子好,2020性价比最高的三款笔记本电脑推荐

    说起选购笔记本,相信很多小伙伴都想着去实体店实际感受下笔记本的使用体验。不过很多对电脑一知半解的小伙伴到了实体店,却很容易被各种“洗脑”以及各种“忽悠”,最终选购了不是自己想入手,且性价比极低的笔记本。 但其实选笔记本也没那么麻烦,确定好预算和用途就很简单了!事实上,大多数用户使用笔记本无非是用来办公、追剧和娱乐,而这些需求主流的高性能轻薄本或者商务本已经足够用了,并且它们的价格也多在4000-6…

    2022年10月2日
    410
  • 电脑软件打不开怎么办(附:电脑所有软件打不开的解决办法)

    我们在一般网站上下载应用的时候,可能都遇到过下载了应用打不开的情况。 这个时候,macOS会提醒「它来自身份不明的开发者」。原因是,有些应用并没有添加开发者的ID签名,又或者是开发者没有经过MacAppStore的认证,在这两种情况下用户就不能够直接打开这些程序。 但其实,要打开未被认证的应用还是可以的。用户只需要进入「系统偏好设置」,打开里面的「安全与隐私」选项。打开之后你就能够看到「允许从以下…

    2022年10月26日
    400
  • 怎么给文件夹加密,原来方法这么简单

    小伙伴你们知道怎么给文件夹进行设置密码吗?估计大多数的人都还不太清楚该怎么设置吧,不过不知道有没有关系呢,因为小编这就来将文件夹设置密码的方法来告诉你们。 我们对电脑的使用已经是越来越广泛了,不论是生活、工作、学习我们都需要使用到电脑。而我们在使用的过程当中也都会储存一些重要一些重要的文件到里边,但如果我们不想让其他人看到的话,该怎么办呢?当然是给文件夹进行加密处理啊。今天小编就和大家探讨一下如何…

    2022年9月22日
    490
  • 如何把手机屏幕调亮度(屏幕调节亮度的方法)

    如今手机厂商越来越重视屏幕体验,AMOLED屏也好、LCD屏也罢,都尽可能地支持高清分辨率、高刷新率,2K+120Hz也成了旗舰手机的标配,有游戏皮偏向的机型还会支持高触控率,咋一看手机的屏幕似乎都很不错,但实际体验起来真的是这样吗? 在大家都将注意力放在分辨率、刷新率这些参数上时,往往就很容易忽视一些基础的屏幕体验,比如亮度调节,这个功能算是元老级的功能点了。回想一下,你现在用的手机最近一次手动…

    2022年5月13日
    1650
  • 怎么把qq群排名靠前,群排名靠前方法

    点击QQ查找,再点点到找QQ群,看到右上角有个李敏镐的小标签,我点了一下,然后点了人数……然后就是上面图片的样子了,看到这里,你们能看到什么项目的商机吗? 我能!!!真的,不信你接着往下看! 我寻思圈的这几个群是干嘛的,于是我点了个进入,接下来看到下面这样的。 看群成员一眼就知道,群里都是假人,也就是僵尸Q。 再说白点,这个群是通过用一些没有人使用的QQ填满群成员,目前是最高两千人,然后把群名设置…

    2022年6月1日
    780

发表回复

登录后才能评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

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

关注微信