`
iaiai
  • 浏览: 2146957 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ScheduledExecutorService执行周期性或定时任务

 
阅读更多
schedule方法被用来延迟指定时间来执行某个指定任务。如果你需要周期性重复执行定时任务可以使用scheduleAtFixedRate或者scheduleWithFixedDelay方法,它们不同的是前者以固定频率执行,后者以相对固定频率执行。

不管任务执行耗时是否大于间隔时间,scheduleAtFixedRate和scheduleWithFixedDelay都不会导致同一个任务并发地被执行。唯一不同的是scheduleWithFixedDelay是当前一个任务结束的时刻,开始结算间隔时间,如0秒开始执行第一次任务,任务耗时5秒,任务间隔时间3秒,那么第二次任务执行的时间是在第8秒开始。

ScheduledExecutorService的实现类,是ScheduledThreadPoolExecutor。ScheduledThreadPoolExecutor对象包含的线程数量是没有可伸缩性的,只会有固定数量的线程。不过你可以通过其构造函数来设定线程的优先级,来降低定时任务线程的系统占用。

特别提示:通过ScheduledExecutorService执行的周期任务,如果任务执行过程中抛出了异常,那么过ScheduledExecutorService就会停止执行任务,且也不会再周期地执行该任务了。所以你如果想保住任务都一直被周期执行,那么catch一切可能的异常。


Timer计时器有管理任务延迟执行("如1000ms后执行任务")以及周期性执行("如每500ms执行一次该任务")。

但是,Timer存在一些缺陷:

1,Timer对调度的支持是基于绝对时间,而不是相对时间的,由此任务对系统时钟的改变是敏感的;ScheduledThreadExecutor只支持相对时间。

2,如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。Timer线程并不捕获异常,所以 TimerTask抛出的未检查的异常会终止timer线程。此时,已经被安排但尚未执行的TimerTask永远不会再执行了,新的任务也不能被调度了。

测试代码:
public class ScheduledExecutorTest {
         public static void main(String[] args) throws Exception {
                   final ScheduledExecutorTest test = new ScheduledExecutorTest();
                   // test.lanuchTimer();
                   // Thread.sleep(1000*5);//5秒钟之后添加新任务
                   // test.addOneTask();
                   test.lanuchTimer2();
                   Thread.sleep(1000 * 5);// 5秒钟之后添加一个新任务
                   test.addOneTask2();
         }

         private final Timer timer = new Timer();

         // 启动计时器
         public void lanuchTimer2() {
                   timer.schedule(new TimerTask() {
                            @Override
                            public void run() {
                                     throw new RuntimeException();
                            }
                   }, 1000 * 3, 500);
         }

         // 向计时器添加一个任务
         public void addOneTask2() {
                   timer.schedule(new TimerTask() {
                            @Override
                            public void run() {
                                     System.out.println("hello world");
                            }
                   }, 1000 * 1, 1000 * 5);
         }

         // public static void main(String[] args) throws Exception {
         // TimerTest test = new TimerTest();
         // test.lanuchTimer();
         // Thread.sleep(1000*5);//5秒钟之后添加一个新任务
         // test.addOneTask();
         // }
}


测试代码结果
Exception in thread "Timer-0" java.lang.RuntimeException
         at com.technology.test.ScheduledExecutorTest$3.run(ScheduledExecutorTest.java:78)
         at java.util.TimerThread.mainLoop(Unknown Source)
         at java.util.TimerThread.run(Unknown Source)
Exception in thread "main" java.lang.IllegalStateException: Timer already cancelled.
         at java.util.Timer.sched(Unknown Source)
         at java.util.Timer.schedule(Unknown Source)
         at com.technology.test.ScheduledExecutorTest.addOneTask2(ScheduledExecutorTest.java:85)
         at com.technology.test.ScheduledExecutorTest.main(ScheduledExecutorTest.java:68)



那么如果使用ScheduledExecutorService呢?

测试代码如下:

public class ScheduledExecutorTest {

         // 线程池能按时间计划来执行任务,允许用户设定计划执行任务的时间,int类型的参数是设定
         // 线程池中线程的最小数目。当任务较多时,线程池可能会自动创建更多的工作线程来执行任务
         public ScheduledExecutorService scheduExec = Executors
                            .newScheduledThreadPool(1);

         // 启动计时器
         public void lanuchTimer() {
                   final Runnable task = new Runnable() {
                            @Override
                            public void run() {
                                     throw new RuntimeException();
                            }
                   };
                   scheduExec.scheduleWithFixedDelay(task, 1000 * 5, 1000 * 10,
                                     TimeUnit.MILLISECONDS);
         }

         // 添加新任务
         public void addOneTask() {
                   final Runnable task = new Runnable() {
                            @Override
                            public void run() {
                                     System.out.println("welcome to china");
                            }
                   };
                   scheduExec.scheduleWithFixedDelay(task, 1000 * 1, 1000,
                                     TimeUnit.MILLISECONDS);
         }

         public static void main(String[] args) throws Exception {
                   final ScheduledExecutorTest test = new ScheduledExecutorTest();
                   // test.lanuchTimer();
                   // Thread.sleep(1000*5);//5秒钟之后添加新任务
                   // test.addOneTask();

                   test.lanuchTimer();
                   Thread.sleep(1000 * 5);// 5秒钟之后添加一个新任务
                   test.addOneTask();

         }
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics