JAVA輕量級定時任務框架

任務流程圖

用戶通過該框架只需在配置文件中配置好繼承了DTJobBase類的路徑和定時任務表達式,即可開啓定時任務,屬於非常輕量級的定時任務框架。具體流程圖如下:

任務流程圖

定時類設計

定時任務抽象類,該類對外提供了一個jobRun()抽象方法,使用時只需繼承該類,然後實現該抽象方法即可。

/**
 * 任務抽象類/已下僅含有核心代碼
 * @author 康駐關
 * Fri Jul 19 09:00:00 CST 2019
 */
public abstract class DTJobBase extends Thread {
	
	private Object _result = null;//用於存放任務執行返回結果
	private Thread _t = null;//用於執行當前線程
	private Exception _e = null;//用於存放捕獲異常
	private long _timeStart = 0;//任務開始時間
	private long _timeCost = 0;//任務消耗時間
	
	/**
	 * 自定義任務接口
	 * @return
	 * @throws Exception
	 */
	public abstract Object jobRun() throws Exception;
	/**
	 * 執行任務並記錄任務花費時間
	 */
	@Override
	public void run() {
		this._timeStart = System.currentTimeMillis();
		try {
			_result = jobRun();
		} catch (Exception ex) {
			this._e = ex;
		}
		this._timeCost = System.currentTimeMillis() - this._timeStart;
	}
}

定時任務工具類設計

定時任務工具類設計,主要是
initProperties(); // 初始化配置
initJobs(); //初始化Job任務
initWatcher(); //掃描並執行定時任務
這三個方法。在checkJobs()方法裏我有一段代碼,不知道是否可以優化程序,有大神看到後跟我留言,謝謝了!

/**
 * 開始定時任務工具類/已下僅含有核心代碼
 * @author 康駐關
 * Fri Jul 19 09:00:00 CST 2019
 */
public class CTUtil {

	private static HashMap<String, String> _CTProperties = null; // 配置文件列表,key爲類名,value爲克隆表達式
	private static HashMap<String, CTJobBase> _CTJobs = null; // 定時任務列表,key爲任務token,value爲定時任務
	private static Boolean _Suspended = false; // 任務暫停
	private static Watcher _Watcher = null;

	/**
	 * 任務檢測類
	 */
	protected static class Watcher implements Runnable {

		private boolean _Cancelled = false;// 是否取消任務
		private Thread _thread = null;// 啓動任務線程
		int _SleepMilliSeconds = 0; // 任務掃描間隔

		public Watcher(int sleepMilliSeconds) {
			if (_thread == null)
				_thread = new Thread(this);
			this._SleepMilliSeconds = sleepMilliSeconds;
		}

		public void Start() //篇幅有限省略
		public void Cancel() //篇幅有限省略

		@Override
		public void run() {
			// 循環掃描定時任務
			while (!_Cancelled) {
				try {
					TimeUnit.MILLISECONDS.sleep(_SleepMilliSeconds);
				} catch (InterruptedException ie) {
					ie.printStackTrace();
				}
				checkJobs();
			}
		}

		protected Boolean isSuspended() //篇幅有限省略
		protected void suspend() //篇幅有限省略

		protected void resume() //篇幅有限省略

		private synchronized void checkJobs() {
			if (_Suspended)
				return;
			try {
				Date _checkTime = new Date();
				_CTJobs.forEach((k, v) -> {
					System.out.println(v.getClass().getName());
					// 如果當前任務沒有執行,並且當前時間在當前定時任務執行時間之後,執行該任務
					if (!v.isPending() && _checkTime.after(v.getNextTrigger()))
						v.start();

					// 我覺得這裏可以優化,如果當前的檢測時間在當前這個任務下次執行之前,同時下次任務執行時間-當前檢測時間小於最小休眠時間,則將休眠時間設爲當前最小值
					// 可以有效降低循環次數,但沒有測試性能是否有優化
					// _SleepMilliSeconds = (int)
					// (((v.getNextTrigger().getTime() - _checkTime.getTime()) >
					// 0
					// && (v.getNextTrigger().getTime() - _checkTime.getTime())
					// < _SleepMilliSeconds)
					// ? (v.getNextTrigger().getTime() - _checkTime.getTime()) :
					// _SleepMilliSeconds);
				});
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void suspend() //篇幅有限省略

	public static void resume() //篇幅有限省略

	public static Boolean isSuspended() //篇幅有限省略

	/**
	 * 手動開啓定時任務
	 * 
	 * @param token
	 * @return
	 */
	protected static int execManually(final String token) //篇幅有限省略

	/**
	 * 獲取某個定時任務克隆表達式
	 * 
	 * @param pName
	 * @return
	 */
	protected static String getCTProperties(final String pName) {
		if (_CTProperties == null)
			initProperties();
		if (_CTProperties.containsKey(pName))
			return _CTProperties.get(pName);
		else
			return null;
	}

	private static void initProperties() {

		if (_CTProperties == null)
			_CTProperties = new HashMap<String, String>();
		Properties p = new Properties();
		File f = new File("conf" + File.separator + "ct.properties");
		FileInputStream fs = null;
		try {
			fs = new FileInputStream(f);
			p.load(fs);
			p.forEach((k, v) -> {
				if (!_CTProperties.containsKey(k))
					_CTProperties.put(String.valueOf(k), String.valueOf(v));

			});
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fs != null)
				try {
					fs.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
	}

	public static void initWatcher() {
		if (_Watcher == null)
			_Watcher = new Watcher(100);
		_Watcher.Start();
		// if(DebugInfo.isDebug()){
		// _Watcher.suspend();
		// }
	}

	public static void initCrontabJobService() {
		initProperties();
		initJobs();
		initWatcher();
	}

	/**
	 * 停止所有定時任務服務
	 */
	public static void stopCrontabJobService() //篇幅有限省略
	/**
	 * 初始化定時任務列表
	 */
	public static void initJobs() {
		if (_CTJobs == null)
			_CTJobs = new HashMap<String, CTJobBase>();
		_CTProperties.forEach((k, v) -> {
			try {
				CTJobBase ctj;
				ctj = (CTJobBase) Class.forName(k).newInstance();
				ctj.setCronExp(v);
				_CTJobs.put("CT-" + HashUtil.getSHA1(k + v), ctj);
			} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
				e.printStackTrace();
			}
		});
	}

}

配置文件

配置克隆表達式的文件內容,我這裏配置的測試是每分鐘執行一次任務

#-----------------------
#Crontab Jobs configure
#-----------------------
#com.kzg.ct.d.TestCTJob = 0 0 0,12 * * ?

#Triggered every 1 minute
com.kzg.ct.d.TestCTJob = 0 * * * * ? 

測試結果

public static void main(String[] args) {
		CTUtil.initCrontabJobService();
}

測試結果
尊重原創,如果轉發請標明鏈接,謝謝! 項目: 鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章