(11)Java多线程之Timer

来源:互联网 发布:mac wine怎么用 编辑:程序博客网 时间:2024/05/23 18:45

  • 引言
  • 使用Timer类
    • 1使用schedule执行定时任务
    • 2 使用守护线程的Timer执行定时任务
    • 3 多个任务验证Timer队列
    • 4 验证scheduleAtFixedRate的追赶型
  • 总结

1.引言

      在JDK中Timer类主要负责定时发布任务。也就是说在指定的时间执行一个任务。Timer类主要负责设置计划任务,真正执行任务的类叫做TimerTask类。
      这两个类之间的关系图:

这里写图片描述

从图中我们可以看到,可以使用Task类的schedule方法执行一个定时任务。

2.使用Timer

首先我们看一下Timer类中schedule的重载:

  • schedule(TimerTask task,Date time)在指定的日期(time)执行一次任务
  • schedule(TimerTask task,long delay)以当前时间为参考,延迟秒数(delay),执行一次任务
  • schedule(TimerTask task,Date firsttime,long period)在指定的日期(firsttime)之后,按照时间间隔(period)循环执行task任务
  • schedule(TimerTask task,long delay,long period)以当前时间为基准,延迟秒数(delay),按照时间间隔(period)循环执行task任务
  • scheduleAtFixedRate(TimerTask task, Date firstTime, long period)schedule(TimerTask task,Date firsttime,long period)类似,但是scheduleAtFixedRate方法具有追赶型
  • cancel()方法,清空任务队列中的所有task任务。注意和TimerTaskcancel()方法区分。

Task任务需要注意的地方:

  • Timer有一个队列的概念,队列里面的task任务顺序执行(如果一个任务是死循环那么后面的任务是不会被执行的),这也意味着,后面的任务有可能不是按时执行(前面的任务耗时太长)
  • 因为Timer有队列的概念,所以Timer不存在线程安全问题
  • Timer具有守护线程和非守护线程之分

2.1使用schedule执行定时任务

  • 首先我们应该定义一个任务类(TimerTask
import java.util.Date;import java.util.TimerTask;public class MyTaskA extends TimerTask {    @Override    public void run() {             System.out.println("MyTaskA执行的时间为:"+new Date().toLocaleString());    }}
  • main函数中执行定时任务
import java.util.Calendar;import java.util.Date;import java.util.Timer;public class app {    public static void main(String[] args) {        System.out.println("当前的时间为:"+new Date().toLocaleString());        //让时间推迟10秒钟        Calendar calendar=Calendar.getInstance();        calendar.add(Calendar.SECOND, 10);        Date runDate=calendar.getTime();        Timer timer=new Timer();        MyTaskA taskA=new MyTaskA();        timer.schedule(taskA, runDate);    }}
  • 运行结果

这里写图片描述

注意:任务运行结束了,但是程序却没有退出,这是因为我们创建的Timer是不守护线程的。

2.2 使用守护线程的Timer执行定时任务

  • 我们只是将上面的例子:修改Timer的定义
//注意:添加了一个trueTimer timer=new Timer(true);
  • 问题是main线程执行结束之后,进程迅速结束,但是我们的task任务没有执行

这里写图片描述

2.3 多个任务验证:Timer队列

  • 创建taskA
import java.util.Date;import java.util.TimerTask;public class MyTaskA extends TimerTask {    @Override    public void run() {             System.out.println("MyTaskA执行的时间为:"+new Date().toLocaleString());        try {            //线程睡眠15秒中            Thread.sleep(15000);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}
  • 创建TaskB
import java.util.Date;import java.util.TimerTask;public class MyTaskB extends TimerTask {    @Override    public void run() {        System.out.println("MyTaskB执行的时间为:"+new Date().toLocaleString());    }}
  • main函数中的代码
import java.util.Calendar;import java.util.Date;import java.util.Timer;public class app {    public static void main(String[] args) {        System.out.println("当前的时间为:"+new Date().toLocaleString());        //让时间推迟1秒钟        Calendar calendar=Calendar.getInstance();        calendar.add(Calendar.SECOND, 1);        Date runDate=calendar.getTime();        //让任务B延迟2秒        Calendar calendar2=Calendar.getInstance();        calendar2.add(Calendar.SECOND, 2);        Date runDateA=calendar.getTime();        //创建定时任务        Timer timer=new Timer();        MyTaskA taskA=new MyTaskA();        MyTaskB taskB=new MyTaskB();        timer.schedule(taskA, runDate);        timer.schedule(taskB, runDateA);    }}
  • 运行结果(注意任务B的运行时间被延迟了)

这里写图片描述

2.4 验证scheduleAtFixedRate的追赶型

追赶型的体现主要表现在:如果任务的执行时间早于当前事件,scheduleAtFixedRate就会体现出追赶型。

  • 创建任务类
import java.util.Date;import java.util.TimerTask;public class MyTaskA extends TimerTask {    @Override    public void run() {        System.out.println("MyTaskA执行的时间为:"+new Date().toLocaleString());    }}
  • 使用schedule方法(main方法,无追赶)
import java.util.Calendar;import java.util.Date;import java.util.Timer;public class app {    public static void main(String[] args) {        System.out.println("当前的时间为:"+new Date().toLocaleString());        //注意,程序的运行时间早于当前时间        Calendar calendar=Calendar.getInstance();        calendar.add(Calendar.SECOND, -5);        Date runDate=calendar.getTime();            Timer timer=new Timer();                MyTaskA taskA=new MyTaskA();            //循环执行,周期为1S        timer.schedule(taskA, runDate,1000);    }}
  • 无追赶的运行结果

这里写图片描述

  • 修改执行方法
import java.util.Calendar;import java.util.Date;import java.util.Timer;public class app {    public static void main(String[] args) {        System.out.println("当前的时间为:"+new Date().toLocaleString());        //注意,程序的运行时间早于当前时间        Calendar calendar=Calendar.getInstance();        calendar.add(Calendar.SECOND, -5);        Date runDate=calendar.getTime();            Timer timer=new Timer();                MyTaskA taskA=new MyTaskA();            //循环执行,周期为1S        timer.scheduleAtFixedRate(taskA, runDate,1000);    }}
  • 追赶型的运行结果

这里写图片描述

通过例子,我们更加的理解追赶性

3.总结

在本篇博客中了解了:

  • 如何实现指定时间执行任务
  • 如何实现指定时间按照周期执行任务
1 0
原创粉丝点击