背景
最近一個(gè)項(xiàng)目上有這么個(gè)功能:數(shù)據(jù)備份及恢復(fù)的任務(wù),可手動(dòng)終止,并可查看任務(wù)的當(dāng)前執(zhí)行進(jìn)度。
本篇的設(shè)計(jì)思想是通用的,只不過采用的是java語言實(shí)現(xiàn)
思考
暫且不談數(shù)據(jù)備份及恢復(fù)如何實(shí)現(xiàn),這里只是大概介紹下通用任務(wù)的實(shí)現(xiàn)
任務(wù)如何進(jìn)行終止
所有的代碼都是運(yùn)行在一個(gè)線程中的,所以想辦法終止正在運(yùn)行中的線程就可以了.
具體的實(shí)現(xiàn)方式:定義一個(gè)開關(guān)變量來進(jìn)行控制就可以了.
private volatile boolean on = true;
public void run(){
while(on && hastNextDataToDeal()){
//執(zhí)行相關(guān)業(yè)務(wù)代碼
}
}
public void stop(){
on = false;
}
如何查看獲取當(dāng)前的執(zhí)行進(jìn)度
-
獲取總體的需要進(jìn)行處理的記錄數(shù)
這里說的記錄數(shù)是一個(gè)很泛的概念,比如數(shù)據(jù)備份這塊,可以把它理解為數(shù)據(jù)庫表的數(shù)量
-
每條記錄處理完畢后,當(dāng)前已處理的記錄數(shù)+1
按照數(shù)據(jù)庫表來說,沒處理過一次表的備份就相應(yīng)的 + 1處理
//總的記錄數(shù)
private volatile int totalRecords;
//當(dāng)前已處理的記錄數(shù)
private volatile int curDealedRecords;
public void run(){
//獲取待處理的總數(shù)
int total = getTotalRecord();
while(on && hastNextRecordToDeal()){
//執(zhí)行相關(guān)業(yè)務(wù)代碼
curDealedRecords++;
}
}
總體設(shè)計(jì)
任務(wù)接口設(shè)計(jì)
具體的任務(wù)需實(shí)現(xiàn)此Task接口
public interface Task {
/**
* 任務(wù)運(yùn)行的業(yè)務(wù)邏輯
* @throws Exception
*/
void run() throws Exception;
/**
* 獲取總體的進(jìn)度
* @return
*/
int getTotalProcess();
/**
* 獲取當(dāng)前的進(jìn)度
* @return
*/
int getCurProcess();
/**
* 停止任務(wù)
*/
void stop();
}
任務(wù)執(zhí)行器設(shè)計(jì)
此任務(wù)執(zhí)行器負(fù)責(zé)任務(wù)的調(diào)度,并可獲取任務(wù)的執(zhí)行信息
public interface TaskService {
/**
* 執(zhí)行任務(wù)
* @param task
* @return 任務(wù)標(biāo)識(shí)
*/
String execute(Task task);
/**
* 獲取任務(wù)信息
* @param taskId
* @return
*/
TaskInfo getTaskInfo(String taskId);
/**
* 停止任務(wù)
* @param taskId
*/
boolean stop(String taskId);
/**
* 任務(wù)信息
*/
public static class TaskInfo{
/**
* 任務(wù)的進(jìn)度
*/
private double process;
/**
* 開始時(shí)間
*/
private Date startTime;
/**
* 結(jié)束時(shí)間
*/
private Date endTime;
}
}
/**
** 任務(wù)執(zhí)行器的大概實(shí)現(xiàn)
**/
public class DefaultTaskService implements TaskService {
/**
* 任務(wù)執(zhí)行線程池
*/
private ThreadPoolExecutor threadPoolExecutor;
/**
* 定時(shí)調(diào)度器
*/
private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
@Override
public String execute(Task task) {
String taskId = null; // 生成任務(wù)唯一標(biāo)識(shí)
//執(zhí)行任務(wù)
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
try {
task.run();
} catch (Exception e) {
e.printStackTrace();
}
}
});
//定時(shí)調(diào)度獲取任務(wù)信息
scheduledThreadPoolExecutor.schedule(new TaskInfoUpdateTask(), 1, TimeUnit.SECONDS);
return taskId;
}
@Override
public TaskInfo getTaskInfo(String taskId) {
return null;
}
@Override
public boolean stop(String taskId) {
return false;
}
}
至此整體的后臺(tái)實(shí)現(xiàn)就已基本完成了,前端的化到時(shí)只要根據(jù)任務(wù)唯一標(biāo)識(shí)去查詢?nèi)蝿?wù)執(zhí)行信息就可以了