定时任务是在指定时间执行程序,或周期性执行计划任务。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的使用非常简单,作为解决方案支持更多的触发机制。