您现在的位置是:首页 > 正文

Timer类

2024-02-29 15:26:36阅读 0

一、Timer类

1.1 概述

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

1.1.1 查看Timer源码

    public Timer(String name) {
        thread.setName(name);
        thread.start();
    }

说明:创建一个Timer就是启动一个新的线程,并且这个新启动的线程不是守护线程,所以任务执行完后,进程还未销毁。

1.2 schedule(TimerTask task, Date time)方法

在指定的日期执行某一次任务

mytask类:

public class mytask extends TimerTask {
    @Override
    public void run() {
        System.out.println("任务执行了");
    }
}

测试类:

public class xtask {
    public static void main(String[] args) throws ParseException {
        Timer timer = new Timer();
        mytask my = new mytask();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String data =  "2019-5-20 17:57:00";
        Date parse = sdf.parse(data);
        timer.schedule(my, parse);
    }
}

Timer实例化对象传入任务参数和时间参数,就可以在特定的时间执行任务。任务执行完后,进程还未销毁,原因是线程不是守护线程。

使用新的Timer()构造方法,调用下面的方法

 Timer timer = new Timer(true);
  public Timer(boolean isDaemon) {
        this("Timer-" + serialNumber(), isDaemon);
    }
   public Timer(String name, boolean isDaemon) {
        thread.setName(name);
        thread.setDaemon(isDaemon);
        thread.start();
    }
  • public final void setDaemon(boolean on)
    将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
    该方法必须在启动线程前调用。

1.3 计划时间已过

如果计划时间已过,则会立刻执行task任务。

public class main {
    public static void main(String[] args) {
        try {
            Timer timer = new Timer();
            myTask myTask = new myTask();
            String date = "2019-8-11 14:25:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parse = simpleDateFormat.parse(date);
            timer.schedule(myTask, parse);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

结果:

时间已经过了

1.4 多个TimerTask任务

一个timer对象可以执行多个任务,而任务是以队列的形式一个个顺序执行的所以执行的时间有可能和预期的时间不太一样。因为前面的任务执行时间过长,导致后面的任务被延迟。

主方法:

public class main {
    public static void main(String[] args) {
        try {
            Timer timer = new Timer();
            myTask myTask1 = new myTask();
            myTask myTask = new myTask();
            String date = "2019-8-11 14:17:20";
            String date1 = "2019-8-11 14:16:20";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parse = simpleDateFormat.parse(date);
            Date parse1 = simpleDateFormat.parse(date1);
            timer.schedule(myTask, parse);
            timer.schedule(myTask1, parse1);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

任务类:

public class myTask extends TimerTask {
    @Override
    public void run() {
        try {
            Thread.sleep(2000);
            System.out.println("这是计划执行的任务" + new Date(System.currentTimeMillis()));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果:

这是计划执行的任务Sun Aug 11 14:17:34 CST 2019
这是计划执行的任务Sun Aug 11 14:17:36 CST 2019

1.5 schedule(TimerTask task, Date firstTime, long period)

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

public class main {
    public static void main(String[] args) {
        try {
            Timer timer = new Timer();
            myTask myTask = new myTask();
            String date = "2019-8-11 14:25:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parse = simpleDateFormat.parse(date);
            timer.schedule(myTask, parse, 1000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

结果:

2019-08-11 14:25:00
2019-08-11 14:25:01
2019-08-11 14:25:02
2019-08-11 14:25:03
2019-08-11 14:25:04
2019-08-11 14:25:05
2019-08-11 14:25:06
2019-08-11 14:25:07
2019-08-11 14:25:08
2019-08-11 14:25:09
2019-08-11 14:25:10
......

时间已过,则立即执行,否则按照指定的时间执行。

1.6 cancle()方法

1.6.1 TmerTask类的cancle方法

将自身从任务队列中清除

主方法:


public class main {
    public static void main(String[] args) {
        try {
            Timer timer = new Timer();
            myTask myTask = new myTask();
            myTask1 task1 = new myTask1();
            String date = "2019-8-11 14:25:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parse = simpleDateFormat.parse(date);
            timer.schedule(myTask, parse,1000);
            myTask.cancel();
            timer.schedule(task1,parse,1000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

结果:

任务2
任务2
任务2
任务2
.......

任务1被取消

1.6.2 Timer类的cancle()方法

将任务队列中的任务全部清除,并且进程也被销毁。

public class main {
    public static void main(String[] args) {
        try {
            Timer timer = new Timer();
            myTask myTask = new myTask();
            myTask1 task1 = new myTask1();
            String date = "2019-8-11 14:25:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parse = simpleDateFormat.parse(date);
            timer.schedule(myTask, parse,1000);
            timer.schedule(task1,parse,1000);
            timer.cancel();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

结果:任务队列中的所有任务被剔除。

1.6.3 Timer的cancle()方法注意

  • 有时候Timer的cancle方法并不会停止任务的进行,而是任务正常执行,原因是cancle()方法并没有抢到queue锁。

任务类:

public class myTask extends TimerTask {
    @Override
    public void run() {
        while (true) {
            System.out.println("任务1");
        }
    }
}

主类:

public class main {
    public static void main(String[] args) {
        try {
            Timer timer = new Timer();
            myTask myTask = new myTask();
            myTask1 task1 = new myTask1();
            String date = "2019-8-11 14:25:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parse = simpleDateFormat.parse(date);
            timer.schedule(myTask, parse, 1000);
            timer.schedule(task1, parse, 1000);
            timer.cancel();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

结果:

任务1
任务1
任务1
任务1
任务1
任务1
............

1.7 其他方法

  • schedule(TimerTask task, long delay)
    在当前时间的基础上经过延迟时间执行任务。

  • schedule(TimerTask task, long delay, long period)
    在当前时间的基础上,经过延迟执行任务,再以period为周期循环执行任务。

任务类:

public class myTask extends TimerTask {
    @Override
    public void run() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime now = LocalDateTime.now();
        String format = now.format(dateTimeFormatter);
        System.out.println("当前时间是" + format);
    }
}

主方法:

public class test {
    public static void main(String[] args) {
        Timer timer = new Timer();
        myTask myTask = new myTask();
        timer.schedule(myTask,1000,1000);
    }
}

结果:

当前时间是2019-08-11 15:10:46
当前时间是2019-08-11 15:10:47
当前时间是2019-08-11 15:10:48
当前时间是2019-08-11 15:10:49
当前时间是2019-08-11 15:10:50
..............

二、 方法scheduleAtFiexedRate()

2.1 方法scheduleAtFiexedRate(TimerTask task, Date firstTime ,long period)和schedule()区别

2.1.1 主要区别在于任务不延时的情况

  • schedule()方法:如果执行任务的时间没有被延时,那么下一次任务执行的时间根据上一次任务开始的时间计算
  • scheduleAtFiexedRate()方法下次执行任务的时间参考的是上一次任务执行完结束的时间。如果任务延时的话,两个方法下一次任务执行参考的是上一次任务执行结束的时间。
2.1.1.1 schedule()方法

任务类:

public class myTask extends TimerTask {
    @Override
    public void run() {
        try {
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime now = LocalDateTime.now();
            String format = now.format(dateTimeFormatter);
            System.out.println("当前任务开始时间是" + format);
            Thread.sleep(1000);
            LocalDateTime now1 = LocalDateTime.now();
            String format1 = now1.format(dateTimeFormatter);
            System.out.println("当前任务结束时间是" + format1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

主方法:

public class test {
    public static void main(String[] args) {
        Timer timer = new Timer();
        myTask myTask = new myTask();
        timer.schedule(myTask,1000,2000);
    }
}

结果:

当前任务开始时间是2019-08-11 15:21:29
当前任务结束时间是2019-08-11 15:21:30
当前任务开始时间是2019-08-11 15:21:31
当前任务结束时间是2019-08-11 15:21:32
当前任务开始时间是2019-08-11 15:21:33
当前任务结束时间是2019-08-11 15:21:34
.............

说明:任务是间隔两秒执行一次,可以看出,下次任务开始时间是上次任务开始时间的基础上加上间隔时间。

2.1.1.2 scheduleAtFiexedRate()方法

2.1.2 追赶执行性

schedule()方法执行的任务超时,则会在当前时间的基础上执行任务,而scheduleAtFiexedRate()方法则会将已经超时未执行的任务补充执行。
任务类:

public class myTask extends TimerTask {
    @Override
    public void run() {
        System.out.println("你好" + LocalDateTime.now());
    }
}

主方法:

public class main {
    public static void main(String[] args) {
        try {
            Timer timer = new Timer();
            myTask myTask = new myTask();
            myTask1 task1 = new myTask1();
            String date = "2019-8-11 14:25:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parse = simpleDateFormat.parse(date);
            timer.scheduleAtFixedRate(myTask, parse,1000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

结果:

你好2019-08-11T16:08:22.133
你好2019-08-11T16:08:22.133
你好2019-08-11T16:08:22.134
你好2019-08-11T16:08:22.134
你好2019-08-11T16:08:22.134
你好2019-08-11T16:08:22.134
你好2019-08-11T16:08:22.134
你好2019-08-11T16:08:22.134
............

说明:比如说从1小时前开始执行的循环任务,现在开始执行,错过的这1小时之内的任务,schedule()方法不执行,而scheduleAtFixedRate()方法会把这错过的任务在一瞬间补上。

2.1.3 相同点:

两个方法都会按顺序执行,所以不要考虑非线程安全的情况

public class xtask {
    public static void main(String[] args) throws ParseException {
        Timer timer = new Timer();
        mytask my = new mytask(timer);
        myTask1 my1 = new myTask1();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String data =  "2019-5-20 20:59:00";
        Date parse = sdf.parse(data);
        timer.scheduleAtFixedRate(my, parse, 1000);
        //timer.schedule(my1, parse, 1000);

    }
}
scheduleAtFiexedRate()方法执行的结果:
任务执行了
要剔除自己了 2019-5-20 21:01:54
任务执行了
要剔除自己了 2019-5-20 21:01:54
任务执行了
要剔除自己了 2019-5-20 21:01:54
任务执行了
要剔除自己了 2019-5-20 21:01:54
任务执行了
要剔除自己了 2019-5-20 21:01:54
任务执行了
要剔除自己了 2019-5-20 21:01:54
.....
scedule()方法执行的结果:
任务执行了
要剔除自己了 2019-5-20 21:03:57
任务执行了
要剔除自己了 2019-5-20 21:03:58
任务执行了
要剔除自己了 2019-5-20 21:03:59
......

2.2 守护线程

如果当前没有其他线程的话,守护线程的任务就不会去执行。

网站文章

  • [NOI 2014复习]斜率优化(BZOJ 1096、BZOJ 1010)

    1.BZOJ 1096 仓库建设题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=1096思路令f[i]=[1,i]f[i]=[1,i]区间,在第i个工厂建立仓库,所需最少总花费。DP方程显然 f[i]=min1≤j<i{f[j]+w[j,i]}+C[i]f[i]=\min_{1\leq j<i}\{f[j]+w[j,i]\}+C[i] 其中

    2024-02-29 15:26:28
  • 如何再linux上部署asp.net项目

    要在 Linux 上部署 ASP.NET 项目,你需要安装 .NET Core 运行时,然后使用 dotnet 命令行工具来运行你的应用。 安装 .NET Core 运行时。你可以在此处下载最新版本的 .NET Core 运行时:https://dotnet.microsoft.com/download 创建 ASP.NET 项目。你可以使用以下命令创建一个新的 ASP.NET 项目: d...

    2024-02-29 15:26:22
  • JVM垃圾回收

    JVM垃圾回收

    Java是支持自动垃圾回收的,有些语言不支持自动垃圾回收(C++)自动垃圾回收不是Java的首创垃圾是什么?在 JVM 中垃圾是指在运行程序中没有任何指针指向的对象,这个对象就是需要被回收的垃圾。哪些...

    2024-02-29 15:25:55
  • windows下安装多个tomcat(解压版tomcat)

    下载解压tomcat后只需修改tomcat下conf-server.xml 里的三处端口号即可修改三处端口号:第一处 修改端口号第二处 修改端口号 URIEncoding= “UTF-8” 这个是配置了字符编码第三处 修改端口号总结只需修改这三处端口号,让每个tomcat都不一样即可...

    2024-02-29 15:25:48
  • hive-NVL、Coalesce、NVL2、NULLIF函数

    1.NVL函数 NVL函数的格式如下:NVL(expr1,expr2) 含义是:如果oracle第一个参数为空那么显示第二个参数的值,如果第一个参数的值不为空,则显示第一个参数本来的值。 例如: SQL&gt; select ename,NVL(comm, -1) from emp; ENAME NVL(COMM,-1) ------- ---- SMITH -1 ALLEN 300 WAR...

    2024-02-29 15:25:41
  • 服务端测试开发必备技能:Mock测试

    服务端测试开发必备技能:Mock测试

    什么是mock测试?Mock 测试就是在测试活动中,对于某些不容易构造或者不容易获取的数据/场景,用一个Mock对象来创建以便测试的测试方法。

    2024-02-29 15:25:12
  • k8s控制器和Pod Template的关系

    k8s控制器和Pod Template的关系

    k8s控制器和Pod Template的关系

    2024-02-29 15:25:04
  • LA 5506 Eight

    LA 5506 Eight

    同样是South Central USA 1998的题,POJ和HDU上的数据比较水,用BFS不加任何优化都可以AC,时间一般是三位数左右。而用A*或IDA*则可以把时间控制在10ms左右,甚至0ms!         然而UVa Live上的这道题是多数据的,用IDA*不加优化都会超时。除此之外题目输入输出很严格,case和case之间必须有空行,在最后一组case之后不能有空行,否则会Wr

    2024-02-29 15:24:58
  • STM32 FOC电机PID学习笔记

    STM32 FOC电机PID学习笔记

    简介 在系统上存在外部干扰的情况下反馈是最好的选择否则使用前馈网络。 为扭矩、通量和速度实施的调节器实际上是比例(P Proportional )、积分(I Integral)、微分 (D Deriv...

    2024-02-29 15:24:31
  • 计算机毕业设计之php的网上汽车销售系统

    计算机毕业设计之php的网上汽车销售系统

    基于php的汽车销售网站将不同的车展示在自己的网站上,用户通过该网站,不仅可以了解各种车款的详情,还能在线预订任何一款爱车,然后到相关的汽车销售实体店现场看车、验车、试车、讨价还价、如果最后满意并确定...

    2024-02-29 15:24:25