閱讀238 返回首頁    go 技術社區[雲棲]


Java定時任務

在日常工作中,定時進行任務調度的業務隨處可見,比如:定時清理係統的臨時文件、有新的活動定時向用戶發送電子郵件、定時檢查係統是否需要更新、定時發送短信等業務。在Java中由兩個類完成定時任務的調度,分別為:java.util.Timer和java.util.TimerTask

創建一個定時任務的步聚:

1、創建一個定時器(Timer)對象

2、調用該對象的schedule(TimerTask task, long delay, long period)scheduleAtFixedRate(TimerTask task, long delay, long period)方法


任務調度方法參數說明:

task:表示要執行的具體任務

delay表示任務創建完成後,第一次什麼時候開始執行該任務,以毫秒為單位

period:表示第一次執行完任務後,後續重複執行該任務的時間間隔是多長,以毫秒為單位


schedule方法與scheduleAtFixedRate方法的區別:

方法 任務執行時間 當任務執行時間大於間隔時間時
schedule 上次任務的結束時間+時間間隔 阻塞式,任務會延後,等待前麵的任務執行完,再執行延務後的任務
scheduleAtFixedRate 上次任務的執行時間+時間間隔 任務不會延後,但要考慮多線程並發的問題。因為當一個任務還沒執行完時,下一個時間間隔任務又會啟動,執行相同的任務

注意:每啟動一個新任務,就會啟動一個新的線程!


實例:

package taskschedule;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

/*
 * 定時器
 * 
 * schedule():下一次任務的執行時間,等於上一次任務的結束時間+時間間隔
 * 
 * scheduleAtFixedRate():下一次任務的執行時間,等於上一次任務的開始時間+時間間隔
 * 
 * 當執行任務的時間大於時間間隔時:
 * schedule任務會延後。
 * scheduleAtFixedRate任務不會延後,仍然在時間間隔內執行,存在並發性,要考慮線程同步的問題
 */
public class TimerTest {
	
	private static int count = 0;
	
	public static void main(String[] args) {
		task_1();
		
		//task_2();
		
		//task_3();
		
		//task_4();
		
		//主線程
		while(true) {
			System.out.println(Calendar.getInstance().get(Calendar.SECOND));
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	//任務1:第一次延遲3秒後啟動任務,後續每隔2秒啟動一次任務
	private static void task_1() {
		new Timer().schedule(new TimerTask(){

			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName() + "定時任務已啟動!");
				
			}}, 3000,2000);	
	}
	
	//任務2:交互執行,方式1:第一次延遲2秒後啟動任務,後續每隔在3秒和6秒之間切換啟動任務
	private static void task_2() {
		class MyTimerTask extends TimerTask {
			
			@Override
			public void run() {
				count = (count+1)%2;
				System.out.println(Thread.currentThread().getName() + "定時任務已啟動!");
				
				new Timer().schedule(new MyTimerTask(), 3000 + 3000 * count);	//循環調用
			}
		}
		
		new Timer().schedule(new MyTimerTask(), 2000);	//2秒後啟動定時器
	}
	
	//任務3:交互執行,方式2:第一次延遲2秒後啟動任務,後續每隔在3秒和6秒之間切換啟動任務
	public static void task_3() {
		new Timer().schedule(new MyTimerTaskA(), 300);
	}
	
	//任務4:演示scheduleAtFixedRate方法,第一次延遲2秒後啟動任務,後續每隔3秒後啟動任務,但任務執行時間大於等於6秒
	public static void task_4() {
		TimerTask task = new TimerTask(){

			@Override
			public void run() {
				System.out.println("execute task:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()));
				try {
					Thread.sleep(6000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "定時任務已啟動!");
			}
		};
		
		new Timer().scheduleAtFixedRate(task, 2000, 3000);
	}
}

//描述2個任務切換啟動
class MyTimerTaskA extends TimerTask {

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + "任務已啟動!");
		new Timer().schedule(new MyTimerTaskB(),2000);
	}
	
}

class MyTimerTaskB extends TimerTask {
	
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + "任務已啟動!");
		new Timer().schedule(new MyTimerTaskA(), 4000);
	}
	
}

任務執行結果:

任務1:


任務2:


任務3:


任務4:


但JDK提供的定時器任務功能有限,不能完成一些複雜的業務,比如:要每年單月的每周星期三的下午5點10分要執行一個任務,JDK則處理不了。不過不要擔心,市麵上已經有開源的任務調度框架:Quartz,官網:https://www.quartz-scheduler.org/

最後更新:2017-04-02 18:44:44

  上一篇:go 典型的 C++ 程序員成長經曆
  下一篇:go 關於安裝蛋疼的ruby gem : tk-win