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

相关推荐

  • 穿越火线烟雾头怎么调,职业选手教你怎么调烟雾头

    我只知道一种W7,大神不喜勿喷,有不对的地方请网友纠正共勉 首先右键屏幕分辨率 对了,在调烟雾头以前要先进入游戏一次,把游戏分辨率调成800.600,然后色彩深度16BIT,然后把游戏退了再开始调烟雾头 然后高级设置,监视器 75HZ,增强色16 然后点确定 鼠标右键,控制面板 调整视屏颜色设置 通过NVIDIA设置,把下面调整成如图,然后应用

    2022年10月4日
    430
  • 团队分工怎么写(最新创业团队分工和职责)

    我们总在强调合伙创业讲究的是团队协作,而组建出一支高效的团队,就必须先做好分工。无论企业规模大小,做好内部结构的规划和人员的安排,才能使企业健康稳定的发展。合伙创业一定要遵循分工原则,否则就会加快企业走向散伙。 在蚂蚁庞大的家族中,一般分蚁后、雄蚁、工蚁和兵蚁四种不同类型。其中蚁后主要负责产卵繁衍后代,雄蚁主要和蚁后进行交配。工蚁是整个蚂蚁家族中数量最多的类型,主要工作是进行建造蚁巢、寻找食物、喂…

    2022年10月21日
    3110
  • 家用投影机哪个品牌最好,市面上最好的10款投影推荐

    随着经济的发展,大家对于家庭影音系统已经不满足于传统的电视了,家用投影仪的出现满足了人们对于在家里实现影院级体验的梦想。而普通分辨率的家用投影仪一直被人诟病的是显示清晰度不够细腻,画质不够好,亮度不够高。所以选购家用投影仪,4K分辨率成了一个非常重要的因素,在市面上4K投影仪的品牌中开始纠结。 最终选择了对这台明基TK800M近半个月的体验,那体验到底如何呢? 先说结论,一个字——爽。 首先,明基…

    2022年8月1日
    660
  • 股权变更办理流程介绍,公司股权变更要去哪里办理

    股权,是有限责任公司或者股份有限公司的股东对公司享有的人身和财产权益的一种综合性权利。即股权是股东基于其股东资格享有的,从公司获得经济利益,并参与公司经营管理的权利。 股权转让,是公司股东依法讲自己的股东权益有偿转让给其他人,使他人取得股权的民事法律行为。 有的公司在成立之初由几位志同道合的朋友一起创立,然而在运营发展的过程中,可能会因为理念不一致,有的股东退出公司经营。也有的公司起初是个人独资的…

    2022年7月24日
    580
  • 网站seo分析案例,如何分析一个网站的seo情况

    一个月前,我站被告知因关键词堆砌等问题导致网站被将降权且停止数据收录。获得百度回馈以后,我站已根据问题回馈内容和白皮书标准进行逐一修改,且每日在网站定量进行原创文章内容的更新并进行了优化。当时说是两周后陆续恢复 ,但是目前都已经过了一个多月了,不仅网站没有恢复权重同时网站的数据收录也在不断地下降,并没有任何的恢复痕迹。 请问大佬们现在我们这个站还存在怎样的问题谁能给看看?或者说还要继续坚持的必要吗…

    2022年7月12日
    530
  • excel破解加密文件(xlsx格式文件加密破解方法)

    当时我就破解了税务局这份表格的密码,不过当初怕说出方法后,被别人乱改这份模板,所以直到今天才说明。 打开模板,可以看到各种功能都是灰色的,也就是工作表被保护了。 这个我是借助VBA破解的。 在开发工具,点VB,进入后台,插入模块,将代码粘贴进去,点运行。 运行后,稍等片刻,就可以破解。注意观察菜单栏,灰色的功能什么时候恢复正常的。整个操作过程,大概7秒。 财务工作中,你是否遇到焦头烂额不知如何解决…

    2022年5月12日
    3210
  • 网站推广专家,教你怎么提高网站搜索排名

    现在很多企业都开始建设自己的网站,其中以营销型网站为主,因为企业建设网站的主要目的就是营销,而营销型网站正是专门为营销设计的。那么,营销型网站的建设流程是否与普通的网站一致呢?接下来卡卡就和大家分享一下福州网站推广专家介绍营销型网站的建设流程。 首先就是域名的注册 域名相信大家都知道,也就是网址,这是为了用一些简洁的字符让人家更容易记住网站,对于域名的获取方法有两种,一种是在互联网上免费注册;第二…

    2022年6月19日
    570
  • 弱电解质有哪些,快速带你了解弱电解质的概念

    一、强、弱电解质的相关判断 1.概念和种类 2.电离、电解质、非电解质、强电解质和弱电解质的相互关系 3.强、弱电解质与化合物类型的关系 强电解质主要是大部分的离子化合物及某些共价化合物,弱电解质主要是某些共价化合物。 分类 举例 强电解质 ①强酸:HCl、H2SO4、HNO3、HClO4、HBr、HI等 ②强碱:NaOH、KOH、Ca(OH)2、Ba(OH)2等 ③大多数盐:钠盐、钾盐、硝酸盐等…

    2022年9月16日
    560
  • 内账是什么,一文带你快速了解内账的定义

    内账和外账都要附带原始凭证吗? 1、企业涉及的所有经济业务都要在内账中反映。 2、无法在外账处理的账务,其原始票据粘连在内账凭证后;在外账中反映的账务,其原始票据无法附在内账中,可在内账分录中注明“见外账×月×号凭证”以方便查阅或以复印件代替,但应考虑复印多少及成本问题。 什么票据可以做外账? 只要是正式的发票或是财政部门监制的行政事业单位收据,都可以用来记账,但选用做外账的单据还需要考虑企业的实…

    2022年9月28日
    1490
  • 微信公众号规则名称,微信公众号怎么推广

    微信公众号怎么排名的?微信公众号排名规则。当我们通过一个公众号关键词去搜索公众号的时候,出现了许多公众号,以下是微信公众号怎么排名的内容。 微信公众号怎么排名的? 微信公众号是按以下内容来排名的: 1.微信公众账号名称 这个就跟seo网站里面的title标签作用一样,完全匹配优先(这点很肯定),分词匹配的排名会比较差。  2.功能介绍 相当于description,目前在微信优化里面比较重要,具体…

    2022年7月29日
    640

发表回复

登录后才能评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

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

关注微信