天天看点

使用Timer和ScheduledThreadPoolExecutor执行定时任务

定时任务是在指定时间执行程序,或周期性执行计划任务。java中实现定时任务的方法有很多,主要jdk自带的一些方法以及开源程序如qurtz。

timer只是充当了一个执行者的角色,真正的任务逻辑是通过一个叫做timertask的抽象类完成的,timertask也是java.util包下面的类,

它是一个实现了runnable接口的抽象类,包含一个抽象方法run( )方法,需要我们自己去提供具体的业务实现。

timer 的优点在于简单易用,但由于所有任务都是由同一个线程来调度,

因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。

示例代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

<code>public</code> <code>class</code> <code>timertest { </code>

<code>    </code><code>//被执行的任务必须继承timertask,并且实现run方法</code>

<code>    </code><code>static</code> <code>class</code> <code>mytimertask1 </code><code>extends</code> <code>timertask { </code>

<code>        </code><code>public</code> <code>void</code> <code>run() { </code>

<code>            </code><code>system.out.println(</code><code>"执行当前线程"</code><code>+thread.currentthread().getname()); </code>

<code>        </code><code>} </code>

<code>    </code><code>}    </code>

<code>    </code><code>/**</code>

<code>     </code><code>* timer线程不会捕获异常,所以timertask抛出的未检查的异常会终止timer线程。</code>

<code>     </code><code>* 如果timer线程中存在多个计划任务,其中一个计划任务抛出未检查的异常,则会引起整个timer线程结束,从而导致其他计划任务无法得到继续执行。  </code>

<code>     </code><code>* timer线程时基于绝对时间,因此计划任务对系统的时间的改变是敏感的。</code>

<code>     </code><code>* timer是单线程,如果某个任务很耗时,可能会影响其他计划任务的执行。</code>

<code>     </code><code>* @param args</code>

<code>     </code><code>* @throws parseexception</code>

<code>     </code><code>* @throws interruptedexception</code>

<code>     </code><code>*/</code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) </code><code>throws</code> <code>parseexception, interruptedexception { </code>

<code>        </code><code>timer timer = </code><code>new</code> <code>timer(); </code>

<code>        </code><code>/**</code>

<code>         </code><code>* scheduleatfixedrate方式</code>

<code>         </code><code>* 设定两秒后执行任务</code>

<code>         </code><code>*/</code>

<code>        </code><code>timer.scheduleatfixedrate(</code><code>new</code> <code>mytimertask1(), </code><code>2000</code><code>,</code><code>1000</code><code>);</code>

<code>         </code><code>* schedule添加date参数</code>

<code>         </code><code>* 设定任务在执行时间执行</code>

<code>//        simpledateformat dateformatter = new simpledateformat("yyyy/mm/dd hh:mm:ss"); </code>

<code>//        date time = dateformatter.parse("2016/03/28 14:40:00"); </code>

<code>//        timer.schedule(new mytimertask1(), time);</code>

<code>        </code><code>//启动mytimertask1线程后,主线程休眠五秒钟,给mytimertask1五秒的执行时间</code>

<code>        </code><code>thread.sleep(</code><code>5000</code><code>);</code>

<code>        </code><code>//终止timer线程</code>

<code>        </code><code>timer.cancel();</code>

<code>}</code>

  jdk 5.0以后推荐使用scheduledthreadpoolexecutor。关于timer简单了解即可。

scheduledthreadpoolexecutor属于executor framework,

它除了能处理异常外,还可以以多线程方式执行定时任务。

timer类是通过单线程来执行所有的timertask任务的,如果一个任务的执行过程非常耗时,将会导致其他任务的时效性出现问题。

而 scheduledthreadpoolexecutor是基于线程池的多线程执行任务,不会存在这样的问题。

通过一个实例学习:

<code>public</code> <code>class</code> <code>scheduledthreadpoolexecutortest {</code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) { </code>

<code>        </code><code>//获得实例,并且设置它的容量为5个 </code>

<code>        </code><code>scheduledthreadpoolexecutor sexecutor=</code><code>new</code> <code>scheduledthreadpoolexecutor(</code><code>5</code><code>);</code>

<code>        </code><code>mytask task = </code><code>new</code> <code>mytask();</code>

<code>        </code><code>//隔2秒后开始执行任务,并且在上一次任务开始后隔一秒再执行一次</code>

<code>//      sexecutor.schedulewithfixeddelay(task, 2, 1, timeunit.seconds); </code>

<code>        </code><code>//隔6秒后执行一次,但只会执行一次</code>

<code>        </code><code>sexecutor.schedule(task, </code><code>6</code><code>, timeunit.seconds);</code>

<code>         </code><code>* 和timer类似,也可以直接在任务的run()方法中调用调度方法停止</code>

<code>         </code><code>* 这个方法会平滑的关闭调度器,等待所有任务结束</code>

<code>        </code><code>sexecutor.shutdown();</code>

<code>        </code> 

<code>    </code><code>}</code>

<code>    </code> 

<code>    </code><code>static</code> <code>class</code> <code>mytask </code><code>implements</code> <code>runnable{</code>

<code>        </code><code>@override</code>

<code>        </code><code>public</code> <code>void</code> <code>run() {</code>

<code>            </code><code>system.out.println(</code><code>"当前执行的线程"</code><code>+thread.currentthread().getname());</code>

<code>        </code><code>}</code>

qurtz的使用非常简单,作为解决方案支持更多的触发机制。