當前位置:編程學習大全網 - 編程語言 - 為什麽使用java 任務調度系統

為什麽使用java 任務調度系統

Timer

相信大家都已經非常熟悉 java.util.Timer 了,它是最簡單的壹種實現任務調度的方法,下面給出壹個具體的例子:

清單 1. 使用 Timer 進行任務調度

package com.ibm.scheduler;

import java.util.Timer;

import java.util.TimerTask;

public class TimerTest extends TimerTask {

private String jobName = "";

public TimerTest(String jobName) {

super();

this.jobName = jobName;

}

@Override

public void run() {

System.out.println("execute " + jobName);

}

public static void main(String[] args) {

Timer timer = new Timer();

long delay1 = 1 * 1000;

long period1 = 1000;

// 從現在開始 1 秒鐘之後,每隔 1 秒鐘執行壹次 job1

timer.schedule(new TimerTest("job1"), delay1, period1);

long delay2 = 2 * 1000;

long period2 = 2000;

// 從現在開始 2 秒鐘之後,每隔 2 秒鐘執行壹次 job2

timer.schedule(new TimerTest("job2"), delay2, period2);

}

}

Output:

execute job1

execute job1

execute job2

execute job1

execute job1

execute job2

使用 Timer 實現任務調度的核心類是 Timer 和 TimerTask。其中 Timer 負責設定 TimerTask 的起始與間隔執行時間。使用者只需要創建壹個 TimerTask 的繼承類,實現自己的 run 方法,然後將其丟給 Timer 去執行即可。

Timer 的設計核心是壹個 TaskList 和壹個 TaskThread。Timer 將接收到的任務丟到自己的 TaskList 中,TaskList 按照 Task 的最初執行時間進行排序。TimerThread 在創建 Timer 時會啟動成為壹個守護線程。這個線程會輪詢所有任務,找到壹個最近要執行的任務,然後休眠,當到達最近要執行任務的開始時間點,TimerThread 被喚醒並執行該任務。之後 TimerThread 更新最近壹個要執行的任務,繼續休眠。

Timer 的優點在於簡單易用,但由於所有任務都是由同壹個線程來調度,因此所有任務都是串行執行的,同壹時間只能有壹個任務在執行,前壹個任務的延遲或異常都將會影響到之後的任務。

回頁首

ScheduledExecutor

鑒於 Timer 的上述缺陷,Java 5 推出了基於線程池設計的 ScheduledExecutor。其設計思想是,每壹個被調度的任務都會由線程池中壹個線程去執行,因此任務是並發執行的,相互之間不會受到幹擾。需要註意的是,只有當任務的執行時間到來時,ScheduedExecutor 才會真正啟動壹個線程,其余時間 ScheduledExecutor 都是在輪詢任務的狀態。

清單 2. 使用 ScheduledExecutor 進行任務調度

package com.ibm.scheduler;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class ScheduledExecutorTest implements Runnable {

private String jobName = "";

public ScheduledExecutorTest(String jobName) {

super();

this.jobName = jobName;

}

@Override

public void run() {

System.out.println("execute " + jobName);

}

public static void main(String[] args) {

ScheduledExecutorService service = Executors.newScheduledThreadPool(10);

long initialDelay1 = 1;

long period1 = 1;

// 從現在開始1秒鐘之後,每隔1秒鐘執行壹次job1

service.scheduleAtFixedRate(

new ScheduledExecutorTest("job1"), initialDelay1,

period1, TimeUnit.SECONDS);

long initialDelay2 = 1;

long delay2 = 1;

// 從現在開始2秒鐘之後,每隔2秒鐘執行壹次job2

service.scheduleWithFixedDelay(

new ScheduledExecutorTest("job2"), initialDelay2,

delay2, TimeUnit.SECONDS);

}

}

Output:

execute job1

execute job1

execute job2

execute job1

execute job1

execute job2

清單 2 展示了 ScheduledExecutorService 中兩種最常用的調度方法 ScheduleAtFixedRate 和 ScheduleWithFixedDelay。ScheduleAtFixedRate 每次執行時間為上壹次任務開始起向後推壹個時間間隔,即每次執行時間為 :initialDelay, initialDelay+period, initialDelay+2*period, …;ScheduleWithFixedDelay 每次執行時間為上壹次任務結束起向後推壹個時間間隔,即每次執行時間為:initialDelay, initialDelay+executeTime+delay, initialDelay+2*executeTime+2*delay。由此可見,ScheduleAtFixedRate 是基於固定時間間隔進行任務調度,ScheduleWithFixedDelay 取決於每次任務執行的時間長短,是基於不固定時間間隔進行任務調度。

回頁首

用 ScheduledExecutor 和 Calendar 實現復雜任務調度

Timer 和 ScheduledExecutor 都僅能提供基於開始時間與重復間隔的任務調度,不能勝任更加復雜的調度需求。比如,設置每星期二的 16:38:10 執行任務。該功能使用 Timer 和 ScheduledExecutor 都不能直接實現,但我們可以借助 Calendar 間接實現該功能。

清單 3. 使用 ScheduledExcetuor 和 Calendar 進行任務調度

package com.ibm.scheduler;

import java.util.Calendar;

import java.util.Date;

import java.util.TimerTask;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class ScheduledExceutorTest2 extends TimerTask {

private String jobName = "";

public ScheduledExceutorTest2(String jobName) {

super();

this.jobName = jobName;

}

@Override

public void run() {

System.out.println("Date = "+new Date()+", execute " + jobName);

}

/**

* 計算從當前時間currentDate開始,滿足條件dayOfWeek, hourOfDay,

* minuteOfHour, secondOfMinite的最近時間

* @return

*/

public Calendar getEarliestDate(Calendar currentDate, int dayOfWeek,

int hourOfDay, int minuteOfHour, int secondOfMinite) {

//計算當前時間的WEEK_OF_YEAR,DAY_OF_WEEK, HOUR_OF_DAY, MINUTE,SECOND等各個字段值

int currentWeekOfYear = currentDate.get(Calendar.WEEK_OF_YEAR);

int currentDayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK);

int currentHour = currentDate.get(Calendar.HOUR_OF_DAY);

int currentMinute = currentDate.get(Calendar.MINUTE);

int currentSecond = currentDate.get(Calendar.SECOND);

//如果輸入條件中的dayOfWeek小於當前日期的dayOfWeek,則WEEK_OF_YEAR需要推遲壹周

boolean weekLater = false;

if (dayOfWeek < currentDayOfWeek) {

weekLater = true;

} else if (dayOfWeek == currentDayOfWeek) {

//當輸入條件與當前日期的dayOfWeek相等時,如果輸入條件中的

//hourOfDay小於當前日期的

//currentHour,則WEEK_OF_YEAR需要推遲壹周

if (hourOfDay < currentHour) {

weekLater = true;

} else if (hourOfDay == currentHour) {

//當輸入條件與當前日期的dayOfWeek, hourOfDay相等時,

//如果輸入條件中的minuteOfHour小於當前日期的

//currentMinute,則WEEK_OF_YEAR需要推遲壹周

if (minuteOfHour < currentMinute) {

weekLater = true;

} else if (minuteOfHour == currentSecond) {

//當輸入條件與當前日期的dayOfWeek, hourOfDay,

//minuteOfHour相等時,如果輸入條件中的

//secondOfMinite小於當前日期的currentSecond,

//則WEEK_OF_YEAR需要推遲壹周

if (secondOfMinite < currentSecond) {

weekLater = true;

}

}

}

}

if (weekLater) {

//設置當前日期中的WEEK_OF_YEAR為當前周推遲壹周

currentDate.set(Calendar.WEEK_OF_YEAR, currentWeekOfYear + 1);

}

// 設置當前日期中的DAY_OF_WEEK,HOUR_OF_DAY,MINUTE,SECOND為輸入條件中的值。

currentDate.set(Calendar.DAY_OF_WEEK, dayOfWeek);

currentDate.set(Calendar.HOUR_OF_DAY, hourOfDay);

currentDate.set(Calendar.MINUTE, minuteOfHour);

currentDate.set(Calendar.SECOND, secondOfMinite);

return currentDate;

}

public static void main(String[] args) throws Exception {

ScheduledExceutorTest2 test = new ScheduledExceutorTest2("job1");

//獲取當前時間

Calendar currentDate = Calendar.getInstance();

long currentDateLong = currentDate.getTime().getTime();

System.out.println("Current Date = " + currentDate.getTime().toString());

//計算滿足條件的最近壹次執行時間

Calendar earliestDate = test

.getEarliestDate(currentDate, 3, 16, 38, 10);

long earliestDateLong = earliestDate.getTime().getTime();

System.out.println("Earliest Date = "

+ earliestDate.getTime().toString());

//計算從當前時間到最近壹次執行時間的時間間隔

long delay = earliestDateLong - currentDateLong;

//計算執行周期為壹星期

long period = 7 * 24 * 60 * 60 * 1000;

ScheduledExecutorService service = Executors.newScheduledThreadPool(10);

//從現在開始delay毫秒之後,每隔壹星期執行壹次job1

service.scheduleAtFixedRate(test, delay, period,

TimeUnit.MILLISECONDS);

}

}

Output:

Current Date = Wed Feb 02 17:32:01 CST 2011

Earliest Date = Tue Feb 8 16:38:10 CST 2011

Date = Tue Feb 8 16:38:10 CST 2011, execute job1

Date = Tue Feb 15 16:38:10 CST 2011, execute job1

  • 上一篇:編程銷售人員
  • 下一篇:職場人如何利用下班時間自我提升?
  • copyright 2024編程學習大全網