zoukankan      html  css  js  c++  java
  • 一步一步学多线程-Timer

      在执行定时任务的时候可以用Timer来实现,现在小编对学到的进行一次总结,先来看一个demo

     1 public class TimerTest {
     2 
     3     public static void main(String[] args) throws ParseException {
     4         Date date=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-08-17 11:18:00");
     5         new Timer().schedule(new TimerTask() {
     6             @Override
     7             public void run() {
     8                 System.out.println(new Date().getSeconds()+"  执行");
     9             }
    10         }, date);
    11     }
    12 }

      这段代码的意思是,先建一个Timer,Timer开始执行的时间是” 2017-08-17 11:18:00”。

    Timer重复执行

      上述代码Timer只会执行一次,如果我们想让定时任务每隔一段时间就执行呢?此时可以用Timer提供的schedule方法的另一个重载 public void schedule(TimerTask task, long delay, long period)。意思是Timer在delay的时候开始执行,每隔period时间长度执行一次。

     1 public class TimerTest {
     2 
     3     public static void main(String[] args) throws ParseException {
     4         Date date=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-08-17 11:18:00");
     5         new Timer().schedule(new TimerTask() {
     6             @Override
     7             public void run() {
     8                 System.out.println(new Date().getSeconds()+"  执行");
     9             }
    10         }, date,1000);
    11     }
    12 }

    执行结果

      37  执行

      38  执行

      39  执行

      40  执行

      ……

    Timer执行延时

      在执行TimerTask的时候可能会出现线程执行时间过长的情况,超过了Timer的等待时间。此时会是什么情况呢?

      

     1 public class TimerTest {
     2 
     3     public static void main(String[] args) throws ParseException {
     4         Date date=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-08-17 11:18:00");
     5         new Timer().schedule(new TimerTask() {
     6             @Override
     7             public void run() {
     8                 System.out.println(new Date().getSeconds()+"  开始执行");
     9                 try {
    10                     Thread.sleep(2000);
    11                     System.out.println(new Date().getSeconds()+"  执行结束");
    12                 } catch (InterruptedException e) {
    13                     e.printStackTrace();
    14                 }
    15             }
    16         }, date,1000);
    17     }
    18 }

    看执行结果

      0  开始执行

      2  执行结束

      2  开始执行

      4  执行结束

      4  开始执行

      6  执行结束

      6  开始执行

      8  执行结束

      8  开始执行

    scheduleAtFixedRate

      使用schedule方法执行Timer任务,如果开始的时间是在当前时间之前,Timer并不会对之前没有执行的任务进行补充执行。也就是延时之后,那么Timer就从当前时间开始接着按照间隔时间执行。但是有时候我们的需求更加关注的执行的频率,需要把因为延时而导致没有执行的任务补充回来,此时就需要用到scheduleAtFiexdRate。

     1 public class TimerTest {
     2 
     3     public static void main(String[] args) throws ParseException {
     4         final Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-08-17 11:52:00");
     5         new Timer().scheduleAtFixedRate(new TimerTask() {
     6             @Override
     7             public void run() {
     8                 System.out.println(date);
     9                 System.out.println(new Date().getSeconds() + "  开始执行");
    10                 System.out.println("执行了");
    11                 System.out.println(new Date().getSeconds() + "  执行结束");
    12 
    13             }
    14         }, date, 10000);
    15     }
    16 }

    执行结果 

      39  开始执行

      执行了

      39  执行结束

      Thu Aug 17 11:52:00 CST 2017

      39  开始执行

      执行了

      39  执行结束

      Thu Aug 17 11:52:00 CST 2017

      40  开始执行

      执行了

      40  执行结束

      通过执行结果可以看出来,scheduleAtFixedRate上来就先将缺失的执行补上,然后再开始按照间隔时间一次一次执行。

    将Timer设置成守护线程

     1 public class TimerTest {
     2 
     3     public static void main(String[] args) throws ParseException {
     4         final Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-08-17 11:52:00");
     5         Timer timer=new Timer();
     6         TimerTask timerTask= new TimerTask() {
     7             @Override
     8             public void run() {
     9                 System.out.println(date);
    10                 System.out.println(new Date().getSeconds() + "  开始执行");
    11                 System.out.println("执行了");
    12                 System.out.println(new Date().getSeconds() + "  执行结束");
    13 
    14             }
    15         };
    16         timer.schedule(timerTask, date);
    17     }
    18 }

      在执行完代码之后,程序仍然在运行。看Timer.class的源代码可以发现Timer是创建了一个新的线程,而持续跟踪代码发现,新的线程进行了一个while(true)循环,再其中进入了等待状态。

    1 public Timer(String name) {
    2     thread.setName(name);
    3     thread.start();
    4 }

    解决办法

      将Timer设置成守护线程,Timer有个构造函数。

    1 public Timer(boolean isDaemon) {
    2     this("Timer-" + serialNumber(), isDaemon);
    3 }

      所以我们在将new Timer()改为new Timer(true)即可。

    TimerTask和Timer的cancel方法 

      TimerTask的cancel方法是关闭这个任务,Timer的cancel方法是关闭整个Timer。

      Timer的执行实际上是启动了一个线程然后,线程中维护了一个队列,然后把TimerTask放入队列中。TimerTask的cancel方法就是将自身从任务队列中移除。Timer的cancel方法,是将队列中的任务全部清空。

  • 相关阅读:
    一个网络狂人的财富轨迹
    婚姻的精髓
    软件史上最伟大的十大程序员
    由瓜子理论引出的人力资源管理启示
    感情裂缝的"维修工" 在生活抛锚的地方起航
    寻找更新过的数据
    asp.net mvc中TempData和ViewData的区别
    SQL Server Backup
    VS字符串时间转换用法
    SQL Server 根据动态条件insert,update语句
  • 原文地址:https://www.cnblogs.com/fhhk/p/7382017.html
Copyright © 2011-2022 走看看