Java多线程编程核心技术第五章笔记:定时器Timer

1、JDK库中Timer主要负责计划任务的功能,也就是说在指定的时间开始执行某一个任务;

定时器五大方法的练习:

1、schedule(TimeTask task,Date time):在指定的日期执行一次某一任务;
  1. 在未来执行的效果:如果不将Timer改成守护线程,那么每创建一个就是启动了一个新的线程这个新启动的线程并不是守护线程,它一直会处于运行状态,如果将新创建的Timer改成守护线程,程序运行后迅速结束当前的进程,并且TimeerTask中的任务不再被运行,因为进程已经结束了;
  2. 提前当前时间执行任务的效果:立即执行task任务;
    当没有设置为守护线程而在未来执行任务时:
    在这里插入图片描述
    设置为守护线程后:在未来执行:程序运行后迅速结束当前的进程,并且TimeerTask中的任务不再被运行,因为进程已经结束了;
    在这里插入图片描述
代码:
package Day30.Test;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;


/**
 1. 定时器Timer的使用
 2. schedule(TimeTask task,Date time):
 3. 在指定的日期执行一次某一任务;
*/
public class Test1 {
    private static Timer timer = new Timer(true);
    static public class MyTask extends TimerTask{
        @Override
        public void run() {
            System.out.println("运行了!时间为:"+new Date());
        }
    }
    public static void main(String[] args) {


        try {
            MyTask task = new MyTask();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dataString = "2019-06-03 22:00:00";
            Date dateRef = sdf.parse(dataString);
            System.out.println("字符串时间:"+ dateRef.toLocaleString()
                    +"当前时间:"+ new Date().toLocaleString());
            timer.schedule(task,dateRef);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
  1. 多个TimerTask任务及延时时,TimerTask是以队列的方式一个一个被顺序执行的,所以执行的时间有可能和预期的时间不一致,因为前面的任务有可能消耗的时间较长,那么后面的任务运行的时间也会被延迟;
    实例:结果,注意时间;运行结果:可以看出task1执行任务是立即执行,因为它是早于当前时间执行task2就是晚于当前时间执行,按时执行;
    在这里插入图片描述
例子代码:
package Day30.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
 1. @author Dangxuchao
 2. @Title: Test2
 3. @ProjectName 5.30 Java多线程编程核心技术第五章:定时器Timer
 4. @Description: TODO
 5. @date 2019/6/3 23:14
*/
public class Test2 {
    private static Timer timer = new Timer();
    static public class MyTask1 extends TimerTask{
        @Override
        public void run() {
            System.out.println("Task1运行了!时间为:"+new Date());
        }
    }
    static public class MyTask2 extends TimerTask{
        @Override
        public void run() {
            System.out.println("Task2运行了!时间为:"+new Date());
        }
    }
    public static void main(String[] args) {
        try {
            MyTask1 myTask1 = new MyTask1();
            MyTask2 myTask2 = new MyTask2();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString1 = "2019-6-3 23:22:50";
            String dateString2 = "2019-6-3 23:23:20";
            Date dateRef1 = sdf1.parse(dateString1);
            Date dateRef2 = sdf2.parse(dateString2);
            System.out.println("字符串时间:"+ dateRef1.toLocaleString()
                    +"当前时间:"+ new Date().toLocaleString());
            System.out.println("字符串时间:"+ dateRef2.toLocaleString()
                    +"当前时间:"+ new Date().toLocaleString());
            timer.schedule(myTask1,dateRef1);
            timer.schedule(myTask2,dateRef2);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
/*
运行结果:可以看出task1执行任务是立即执行,因为它是早于当前时间执行
task2就是晚于当前时间执行,按时执行;
    字符串时间:2019-6-3 23:22:50当前时间:2019-6-3 23:23:01
    字符串时间:2019-6-3 23:23:20当前时间:2019-6-3 23:23:01
    Task1运行了!时间为:Mon Jun 03 23:23:01 CST 2019
    Task2运行了!时间为:Mon Jun 03 23:23:20 CST 2019
*/
  1. 当前行的任务Thread()几秒的话,后面的任务也会被顺序延迟:如图,task本来在32秒的时候执行,可是却在34秒才被执行;
    在这里插入图片描述
2、public void schedule(TimerTask task, Date firstTime, long period) :

作用:在指定的日期之后,按指定的间隔周期性的无限循环地执行某一任务;
7. 在未来执行的效果:从运行结果来看,每隔几秒执行一次TimerTask任务,并且是无限期地重复执行;
8. 在过去的时间点执行的话就是立即打印,并且重复执行;
在这里插入图片描述
9. 任务执行被延时的时候:如果重复执行的时间间隔是4秒,而执行一次任务所花的时间是5秒的花,每间隔5秒才开始下一次执行;
在这里插入图片描述

package Day30.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;


/**
* @author Dangxuchao
* @Title: Test3
* @ProjectName 5.30 Java多线程编程核心技术第五章:定时器Timer
* @Description: schedule(TimerTask task, Date firstTime, long period) :
* 作用:在指定的日期之后,按指定的间隔周期性的无限循环地执行某一任务;
* 1、
* 在未来执行的效果:从运行结果来看,
* 每隔几秒执行一次TimerTask任务,并且是无限期地重复执行;
* @date 2019/6/3 23:42
*/
public class Test3 {
    private static Timer timer = new Timer();
    static public class MyTask3 extends TimerTask{
        @Override
        public void run() {
            System.out.println("运行了,时间为:"+new Date());
        }
    }
    public static void main(String[] args) {
        try{
            MyTask3 myTask3 = new MyTask3();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = "2019-6-3 23:51:00";
            Date dateRef3 = sdf.parse(dateString);
            System.out.println("字符串时间:"+ dateRef3.toLocaleString()
                    +"当前时间:"+ new Date().toLocaleString());
            timer.schedule(myTask3,dateRef3,2000);
        }catch (ParseException e){
            e.printStackTrace();
        }
    }
}
/*
运行时间:


    字符串时间:2019-6-3 23:51:00当前时间:2019-6-3 23:50:27
    运行了,时间为:Mon Jun 03 23:51:00 CST 2019
    运行了,时间为:Mon Jun 03 23:51:02 CST 2019
    运行了,时间为:Mon Jun 03 23:51:04 CST 2019
    运行了,时间为:Mon Jun 03 23:51:06 CST 2019
    运行了,时间为:Mon Jun 03 23:51:08 CST 2019
    运行了,时间为:Mon Jun 03 23:51:10 CST 2019
    运行了,时间为:Mon Jun 03 23:51:12 CST 2019
    运行了,时间为:Mon Jun 03 23:51:14 CST 2019
    运行了,时间为:Mon Jun 03 23:51:16 CST 2019
    运行了,时间为:Mon Jun 03 23:51:18 CST 2019
    运行了,时间为:Mon Jun 03 23:51:20 CST 2019
*/
3、TimerTask类的cancel()方法:将自身从任务队列中清除

在这里插入图片描述

代码:
package Day30.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
* @author Dangxuchao
* @Title: Test4
* @ProjectName 5.30 Java多线程编程核心技术第五章:定时器Timer
* @Description: TimerTask类的cancel()方法:将自身从任务队列中清除
* @date 2019/6/4 0:26
*/
public class Test4 {
    private static Timer timer4 = new Timer();
    static public class MyTask4A extends TimerTask{
        @Override
        public void run() {
            System.out.println("A运行了!时间为:"+new Date());
            this.cancel();
            //timer4.cancel();
        }
    }
    static public class MyTask4B extends TimerTask{
        @Override
        public void run() {
            System.out.println("B运行了!时间为:"+new Date());
        }
    }
    public static void main(String[] args) {
        try{
            MyTask4A task4A = new MyTask4A();
            MyTask4B task4B = new MyTask4B();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString4 = "2019-6-4 00:39:50";

            Date dateRef4 = sdf.parse(dateString4);
            System.out.println("字符串时间:"+ dateRef4.toLocaleString()
                    +"当前时间:"+ new Date().toLocaleString());
            timer4.schedule(task4A,dateRef4,2000);
            timer4.schedule(task4B,dateRef4,2000);
        }catch (ParseException e){
            e.printStackTrace();
        }
    }
}
/*
运行结果:

    字符串时间:2019-6-4 0:39:50当前时间:2019-6-4 0:39:54
    A运行了!时间为:Tue Jun 04 00:39:54 CST 2019
    B运行了!时间为:Tue Jun 04 00:39:54 CST 2019
    B运行了!时间为:Tue Jun 04 00:39:56 CST 2019
    B运行了!时间为:Tue Jun 04 00:39:58 CST 2019
    B运行了!时间为:Tue Jun 04 00:40:00 CST 2019
    B运行了!时间为:Tue Jun 04 00:40:02 CST 2019
    B运行了!时间为:Tue Jun 04 00:40:04 CST 2019
    B运行了!时间为:Tue Jun 04 00:40:06 CST 2019
    B运行了!时间为:Tue Jun 04 00:40:08 CST 2019
*/
4、Timer类的cancel()方法:将任务队列中的全部任务清空:

这里注意一下,有时候Timer的cancel()方法有时候并不能停止执行计划任务,而是正常执行这是因为此方法又是并没有争抢到queue锁,所以TimerTask类中的任务继续正常执行

在这里插入图片描述

5、schedule(TimerTask task,long delay):以当前的时间作为参考时间,在此时间基础上延迟指定delay毫秒后执行一次TimerTask任务;

如图,延迟两秒后:
在这里插入图片描述

package Day30.Test;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
* @author Dangxuchao
* @Title: Test5
* @ProjectName 5.30 Java多线程编程核心技术第五章:定时器Timer
* @Description: 方法schedule(TimerTask task,long delay):
* 以当前的时间作为参考时间,在此时间基础上延迟指定delay毫秒后执行一次TimerTask任务;
* @date 2019/6/4 7:55
*/

public class Test5 {
    static public class MyTask5 extends TimerTask{
        @Override
        public void run() {
            System.out.println("运行,运行时间为:"+new Date());
        }
    }
    public static void main(String[] args) {
        MyTask5 task5 = new MyTask5();
        Timer tiemr = new Timer();
        System.out.println("当前时间为:"+new Date().toLocaleString());
        tiemr.schedule(task5,2000);
    }
}
/*
运行结果:

    当前时间为:2019-6-4 8:02:33
    运行,运行时间为:Tue Jun 04 08:02:35 CST 2019

*/
6、public void schedule(TimerTask task, long delay, long period):延迟执行的条件下加了个周期循环执行;

在这里插入图片描述

scheduleAtFixedRate(TimerTask task, Date firstTime, long period)与public void schedule(TimerTask task, Date firstTime, long period)之间区别:

1、首先来看第一个schedule:
  1. 测试schedule方法任务不延时的情况:周期时间以给定的period为准,任务执行开始时间到下一次任务开始的时间间隔就是周期时间;

在这里插入图片描述

  1. 延时的情况:周期间隔以任务执行时间为准,任务执行延时超出period,以任务执行时间为准;
    在这里插入图片描述
代码:
package Day30.Test;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
* @author Dangxuchao
* @Title: Test6
* @ProjectName 5.30 Java多线程编程核心技术第五章:定时器Timer
* @Description:
* 测试schedule方法不延时的情况
* 还有跟延时时的情况
* @date 2019/6/4 8:09
*/

public class Test6 {
    private static Timer timer = new Timer();
    private static int runCount = 0;

    static public class MyTask6 extends TimerTask{
        @Override
        public void run() {
            try {
                System.out.println("Task开始执行:"+new Date());
                Thread.sleep(1000);
                System.out.println("Task结束执行:"+new Date());
                runCount++;
                if (runCount == 5){
                    timer.cancel();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {


        try {
            MyTask6 task6 = new MyTask6();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = "2019-6-4 8:24:00";
            Date dateRef6 = sdf.parse(dateString);
            System.out.println("字符串时间:"+ dateRef6.toLocaleString()
                    +"当前时间:"+ new Date().toLocaleString());
            timer.schedule(task6,dateRef6,2000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
/*
运行结果:测试schedule方法不延时的情况,可以看出schedule方法不延时重复执行,
是任务执行时间加上间隔时间才是delay循环周期;

    字符串时间:2019-6-4 8:24:00当前时间:2019-6-4 8:23:30
    Task开始执行:Tue Jun 04 08:24:00 CST 2019
    Task结束执行:Tue Jun 04 08:24:01 CST 2019
    Task开始执行:Tue Jun 04 08:24:02 CST 2019
    Task结束执行:Tue Jun 04 08:24:03 CST 2019
    Task开始执行:Tue Jun 04 08:24:04 CST 2019
    Task结束执行:Tue Jun 04 08:24:05 CST 2019
    Task开始执行:Tue Jun 04 08:24:06 CST 2019
    Task结束执行:Tue Jun 04 08:24:07 CST 2019
    Task开始执行:Tue Jun 04 08:24:08 CST 2019
    Task结束执行:Tue Jun 04 08:24:09 CST 2019
*/
下面来看第二个

scheduleAtFixedRate(TimerTask task, Date firstTime,long period)延时与不延时的区别:

  1. 不延时的情况:就是说不在乎你当下的周期时间,这次任务执行完了之后就接着执行下次任务;

在这里插入图片描述

  1. 延时的结果:跟schedule的结果一样:
    在这里插入图片描述
代码:
package Day30.Test;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;


/**
* @author Dangxuchao
* @Title: Test7
* @ProjectName 5.30 Java多线程编程核心技术第五章:定时器Timer
* @Description: scheduleAtFixedRate(TimerTask task, Date firstTime,long period)
* 延时与不延时的区别:
* @date 2019/6/4 8:52
*/
public class Test7 {
    private static Timer timer = new Timer();
    private static int runCount = 0;
    static public class MyTask7 extends TimerTask{
        @Override
        public void run() {

            try {
                System.out.println("开始运行了:"+new Date());
                Thread.sleep(3000);
                System.out.println("结束运行了:"+new Date());
                runCount++;
                if (runCount == 4){
                    timer.cancel();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) {

        try {
            MyTask7 myTask7 = new MyTask7();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = "2019-6-4 8:58:00";
            Date dateRef = sdf.parse(dateString);
            System.out.println("字符串时间:"+dateRef.toLocaleString()
                    +"当前时间:"+new Date());
            timer.scheduleAtFixedRate(myTask7,dateRef,1000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

/*
    延时后的运行结果:,跟schedule的结果一样:

    字符串时间:2019-6-4 8:58:00当前时间:Tue Jun 04 09:01:26 CST 2019
    开始运行了:Tue Jun 04 09:01:26 CST 2019
    结束运行了:Tue Jun 04 09:01:29 CST 2019
    开始运行了:Tue Jun 04 09:01:29 CST 2019
    结束运行了:Tue Jun 04 09:01:32 CST 2019
    开始运行了:Tue Jun 04 09:01:32 CST 2019
    结束运行了:Tue Jun 04 09:01:35 CST 2019
    开始运行了:Tue Jun 04 09:01:35 CST 2019
    结束运行了:Tue Jun 04 09:01:38 CST 2019
*/
/*
不延时的结果:不会被参数中的周期时间period而限制,
本次任务执行完就接着下次的任务执行;
    字符串时间:2019-6-4 8:58:00当前时间:Tue Jun 04 09:02:57 CST 2019
    开始运行了:Tue Jun 04 09:02:57 CST 2019
    结束运行了:Tue Jun 04 09:02:58 CST 2019
    开始运行了:Tue Jun 04 09:02:58 CST 2019
    结束运行了:Tue Jun 04 09:02:59 CST 2019
    开始运行了:Tue Jun 04 09:02:59 CST 2019
    结束运行了:Tue Jun 04 09:03:00 CST 2019
    开始运行了:Tue Jun 04 09:03:00 CST 2019
    结束运行了:Tue Jun 04 09:03:01 CST 2019

*/
8、最后两个测试:
1、验证schedule方法不具有追赶执行性:可以看出9:11:43之前的任务被取消了,不执行了,这就是Task任务不追赶的情况;

在这里插入图片描述

package Day30.Test;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;


/**
* @author Dangxuchao
* @Title: Test8
* @ProjectName 5.30 Java多线程编程核心技术第五章:定时器Timer
* @Description: 验证schedule方法不具有追赶执行性:
* @date 2019/6/4 9:06
*/
public class Test8 {
    private static Timer timer8 = new Timer();
    static public class MyTask8 extends TimerTask{
        @Override
        public void run() {
            System.out.println("开始运行了:"+new Date());
            System.out.println("结束运行了:"+new Date());
        }
    }
    public static void main(String[] args) {

        try {
            MyTask8 task8 = new MyTask8();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = "2019-6-4 9:10:00";
            Date dateRef = sdf.parse(dateString);
            System.out.println("字符串时间:"+dateRef.toLocaleString()
                    +"当前时间:"+new Date());
            timer8.schedule(task8,dateRef,5000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
/*
运行结果:schedule无追赶执行性

    字符串时间:2019-6-4 9:10:00当前时间:Tue Jun 04 09:11:43 CST 2019
    开始运行了:Tue Jun 04 09:11:43 CST 2019
    结束运行了:Tue Jun 04 09:11:43 CST 2019
    开始运行了:Tue Jun 04 09:11:48 CST 2019
    结束运行了:Tue Jun 04 09:11:48 CST 2019
    开始运行了:Tue Jun 04 09:11:53 CST 2019
    结束运行了:Tue Jun 04 09:11:53 CST 2019
    开始运行了:Tue Jun 04 09:11:58 CST 2019
    结束运行了:Tue Jun 04 09:11:58 CST 2019
*/
2、验证scheduleAtFixedRate方法具有追赶性:运行结果:前面时间所对应的任务被补齐了,这就是Task任务追赶执行的特性;

在这里插入图片描述
代码:

package Day30.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
* @author Dangxuchao
* @Title: Test9
* @ProjectName 5.30 Java多线程编程核心技术第五章:定时器Timer
* @Description: 验证scheduleAtFixedRate方法具有追赶性:
* @date 2019/6/4 9:15
*/
public class Test9 {
    private static Timer timer = new Timer();
    public static class MyTask9 extends TimerTask{
        @Override
        public void run() {
            System.out.println("开始执行了:"+ new Date());
            System.out.println("结束执行:"+ new Date());
        }
    }
    public static void main(String[] args) {

        try {
            MyTask9 task9 = new MyTask9();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateString = "2019-6-4 9:20:00";
            Date dateRef = sdf.parse(dateString);
            System.out.println("字符串时间:"+ dateRef.toLocaleString()
                    +"当前时间:"+ new Date().toLocaleString());
            timer.scheduleAtFixedRate(task9,dateRef,2000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
/*
运行结果:前面时间所对应的任务被补齐了,这就是Task任务追赶执行的特性;
    开始执行了:Tue Jun 04 09:22:29 CST 2019
    结束执行:Tue Jun 04 09:22:29 CST 2019
    开始执行了:Tue Jun 04 09:22:29 CST 2019
    结束执行:Tue Jun 04 09:22:29 CST 2019
    开始执行了:Tue Jun 04 09:22:29 CST 2019
    结束执行:Tue Jun 04 09:22:29 CST 2019
    开始执行了:Tue Jun 04 09:22:29 CST 2019
    结束执行:Tue Jun 04 09:22:29 CST 2019
    开始执行了:Tue Jun 04 09:22:30 CST 2019
    结束执行:Tue Jun 04 09:22:30 CST 2019
    开始执行了:Tue Jun 04 09:22:32 CST 2019
    结束执行:Tue Jun 04 09:22:32 CST 2019
    开始执行了:Tue Jun 04 09:22:34 CST 2019
    结束执行:Tue Jun 04 09:22:34 CST 2019
    开始执行了:Tue Jun 04 09:22:36 CST 2019
    结束执行:Tue Jun 04 09:22:36 CST 2019
    开始执行了:Tue Jun 04 09:22:38 CST 2019
    结束执行:Tue Jun 04 09:22:38 CST 2019
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值