如何設(shè)計(jì)可手動(dòng)終止及查看當(dāng)前進(jìn)度的任務(wù)

背景

 最近一個(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)度

  1. 獲取總體的需要進(jìn)行處理的記錄數(shù)

    這里說的記錄數(shù)是一個(gè)很泛的概念,比如數(shù)據(jù)備份這塊,可以把它理解為數(shù)據(jù)庫表的數(shù)量

  2. 每條記錄處理完畢后,當(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í)行信息就可以了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容