多线程编程(九)——定时器Timer

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/swadian2008/article/details/100173207

目录

一、方法schedule(TimerTask task, Date time)——指定日期执行一次任务

二、方法schedule(TimerTask task,Date firstTime,long period)——按时间周期重复执行

三、TimerTask类的cancel()方法和Timer的cancel()方法——任务移除

四、方法schedule(TimerTask task,long delay)——延迟执行

五、schedule不追赶和scheduleAtFixedRate追赶


Timer类的主要作用是设置计划任务,但封装任务的类却是TimerTask类,执行计划任务的代码要放入TimerTask的子类中,因为TimeTask是一个抽象类。

一、方法schedule(TimerTask task, Date time)——指定日期执行一次任务

schedule(TimerTask task, Date time)方法摘取

public abstract class TimerTask implements Runnable {
}

1、TimerTask类为抽象类,实现了Runnable接口,主要用来创建一个新的线程执行任务。

2、Date time 为执行任务的日期,如果该日期早于当前时间,那么程序启动后,任务会立即执行

3、创建一个Timer就是启动一个新线程,其中创建Timer时传true,可以设置此线程为守护线程。

 // 设置定时器开启的线程为守护线程
private static Timer timer = new Timer(true);

4、一个Timer可以执行多个TimerTask任务,TimerTask任务以队列的方式一个个被顺序执行,当前面任务执行时间较长时,会使得后边任务的运行时间也会被延迟,从而出现执行时间于预期时间不一致的情况。

测试代码:

public class MyService {

    // 创建一个定时器
    private static Timer timer = new Timer();

    public static class MyTaskA extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            try {
                System.out.println("MyTaskA任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                // 延长执行时间2s
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static class MyTaskB extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            System.out.println("MytaskB任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }
    }

    public static void main(String[] args) {
        // 创建多个执行任务
        MyTaskA taskA = new MyTaskA();
        MyTaskB taskB = new MyTaskB();
        try {
            Date parse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-08-31 14:42:00");
            System.out.println("当前时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // 计划时间早于当前时间,任务会被立即执行
            timer.schedule(taskA,parse);
            // B任务会收到A任务执行时间的影响,执行时间延迟,从而使实际执行时间与预计执行时间不一致
            timer.schedule(taskB,parse);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

执行结果:

二、方法schedule(TimerTask task,Date firstTime,long period)——按时间周期重复执行

该方法的作用是在指定的日期之后,按指定的时间间隔周期性地无限循环地执行某一任务。

TimerTask task 需要执行的任务

Date firstTime 执行任务开始时间,同样的,如过此时间早于当前时间,任务会被立即执行,反之,会达到未来执行的效果。

long period 任务循环执行的间隔时间周期

注:后边执行任务仍然会受到前边执行任务的影响,出现任务执行延时。

测试代码:

public class MyService {

    // 创建一个定时器
    private static Timer timer = new Timer();

    public static class MyTaskA extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            try {
                System.out.println("MyTaskA任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                // 延长执行时间5s,大于规定的任务执行时间间隔周期,那么任务的执行会按这个延迟时间间隔来执行
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static class MyTaskB extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            System.out.println("MytaskB任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }
    }

    public static void main(String[] args) {
        // 创建多个执行任务
        MyTaskA taskA = new MyTaskA();
        MyTaskB taskB = new MyTaskB();
        try {
            Date parse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-08-31 14:42:00");
            System.out.println("当前时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // 计划时间早于当前时间,任务会被立即执行
            timer.schedule(taskA,parse,4000);
            // B任务会收到A任务执行时间的影响,执行时间延迟,从而使实际执行时间与预计执行时间不一致
            timer.schedule(taskB,parse,4000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

截取测试结果:

三、TimerTask类的cancel()方法和Timer的cancel()方法——任务移除

TimerTask类的cancel()方法是将自身从任务队列中移除,其他任务不受影响。

Timer的cancel()方法是清除全部任务,并使进程终止。

测试代码:

public class MyService {

    // 创建一个定时器
    private static Timer timer = new Timer();

    public static class MyTaskA extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            try {
                System.out.println("MyTaskA任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                // 延长执行时间
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static class MyTaskB extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            System.out.println("MytaskB任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // B任务被执行一次后移除
            this.cancel();
        }
    }

    public static void main(String[] args) {
        // 创建多个执行任务
        MyTaskA taskA = new MyTaskA();
        MyTaskB taskB = new MyTaskB();
        try {
            Date parse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-08-31 14:42:00");
            System.out.println("当前时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // 计划时间早于当前时间,任务会被立即执行
            timer.schedule(taskA,parse,4000);
            // B任务会收到A任务执行时间的影响,执行时间延迟,从而使实际执行时间与预计执行时间不一致
            timer.schedule(taskB,parse,4000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

测试结果:

执行TimerTask类的cancel()方法,只会移除当前单个执行任务,并不会影响其他定时任务的执行,接下来改变调用对象,使用Timer的cancel()方法,我们将看到所有任务都将被终止。

测试代码:

public class MyService {

    // 创建一个定时器
    private static Timer timer = new Timer();

    public static class MyTaskA extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            try {
                System.out.println("MyTaskA任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                // 延长执行时间
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static class MyTaskB extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            System.out.println("MytaskB任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // 使用定时器的移除方法,此时会终止所有任务!!!
            timer.cancel();
        }
    }

    public static void main(String[] args) {
        // 创建多个执行任务
        MyTaskA taskA = new MyTaskA();
        MyTaskB taskB = new MyTaskB();
        try {
            Date parse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-08-31 14:42:00");
            System.out.println("当前时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // 计划时间早于当前时间,任务会被立即执行
            timer.schedule(taskA,parse,4000);
            // B任务会收到A任务执行时间的影响,执行时间延迟,从而使实际执行时间与预计执行时间不一致
            timer.schedule(taskB,parse,4000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

测试结果:

四、方法schedule(TimerTask task,long delay)——延迟执行

方法schedule(TimerTask task,long delay),是以当前时间为参考,然后按照指定延迟时间执行一次任务。

方法schedule(TimerTask task,long delay,long period),以当前时间为参考,按照指定延迟时间,开始周期性的循环执行任务。

测试代码:

public class MyService {

    // 创建一个定时器
    private static Timer timer = new Timer();

    public static class MyTaskA extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            try {
                System.out.println("MyTaskA任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                // 延长执行时间
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static class MyTaskB extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            System.out.println("MytaskB任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }
    }

    public static void main(String[] args) {
        // 创建多个执行任务
        MyTaskA taskA = new MyTaskA();
        MyTaskB taskB = new MyTaskB();
        try {
            Date parse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-08-31 14:42:00");
            System.out.println("当前时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // 延迟执行
            timer.schedule(taskA,4000,4000);
            // B任务会收到A任务执行时间的影响,执行时间延迟,从而使实际执行时间与预计执行时间不一致
            timer.schedule(taskB,4000,4000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

测试结果:

五、schedule不追赶和scheduleAtFixedRate追赶

schedule不追赶,执行时间早于当前时间,程序会以当前时间为开始时间执行任务,前边没有被执行的任务,不再执行

scheduleAtFixedRate追赶,执行时间早于当前时间,程序会以当前时间为开始时间执行任务,前边没有被执行的任务,全部会被补充执行

public class MyService {

    // 创建一个定时器
    private static Timer timer = new Timer();

    public static class MyTaskA extends TimerTask{
        @Override
        public void run() {
            // 开启一个线程执行定时任务
            try {
                System.out.println("MyTaskA任务执行,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                // 延长执行时间
                Thread.sleep(1000);
                System.out.println("MyTaskA任务结束,时间为:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        // 创建多个执行任务
        MyTaskA taskA = new MyTaskA();
        try {
            Date parse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-08-31 14:42:00");
            System.out.println("当前时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // schedule
            timer.schedule(taskA,parse,3000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

测试结果:

接下来把执行代码换成:timer.scheduleAtFixedRate(taskA,parse,4000);

public static void main(String[] args) {
        // 创建多个执行任务
        MyTaskA taskA = new MyTaskA();
        try {
            Date parse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-08-31 14:42:00");
            System.out.println("当前时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // schedule
            timer.scheduleAtFixedRate(taskA,parse,3000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

测试结果:

猜你喜欢

转载自blog.csdn.net/swadian2008/article/details/100173207