天天看點

使用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的使用非常簡單,作為解決方案支援更多的觸發機制。