如何设计可手动终止及查看当前进度的任务

背景

 最近一个项目上有这么个功能:数据备份及恢复的任务,可手动终止,并可查看任务的当前执行进度。
 本篇的设计思想是通用的,只不过采用的是java语言实现

思考

暂且不谈数据备份及恢复如何实现,这里只是大概介绍下通用任务的实现

任务如何进行终止

所有的代码都是运行在一个线程中的,所以想办法终止正在运行中的线程就可以了.

具体的实现方式:定义一个开关变量来进行控制就可以了.

private volatile boolean on = true;
public void run(){
  while(on && hastNextDataToDeal()){
    //执行相关业务代码
  }
}

public void stop(){
  on = false;
}

如何查看获取当前的执行进度

  1. 获取总体的需要进行处理的记录数

    这里说的记录数是一个很泛的概念,比如数据备份这块,可以把它理解为数据库表的数量

  2. 每条记录处理完毕后,当前已处理的记录数+1

    按照数据库表来说,没处理过一次表的备份就相应的 + 1处理

//总的记录数
private volatile int totalRecords;
//当前已处理的记录数
private volatile int curDealedRecords;

public void run(){
  //获取待处理的总数
  int total = getTotalRecord();
  
  while(on && hastNextRecordToDeal()){
    //执行相关业务代码
    curDealedRecords++;
  }
}

总体设计

任务接口设计

具体的任务需实现此Task接口

public interface Task {

    /**
     * 任务运行的业务逻辑
     * @throws Exception
     */
    void run() throws Exception;

    /**
     * 获取总体的进度
     * @return
     */
    int getTotalProcess();

    /**
     * 获取当前的进度
     * @return
     */
    int getCurProcess();

    /**
     * 停止任务
     */
    void stop();
}

任务执行器设计

此任务执行器负责任务的调度,并可获取任务的执行信息

public interface TaskService {

    /**
     * 执行任务
     * @param task
     * @return 任务标识
     */
    String execute(Task task);

    /**
     * 获取任务信息
     * @param taskId
     * @return
     */
    TaskInfo getTaskInfo(String taskId);

    /**
     * 停止任务
     * @param taskId
     */
    boolean stop(String taskId);


    /**
     * 任务信息
     */
    public static class TaskInfo{
        /**
         * 任务的进度
         */
        private double process;

        /**
         * 开始时间
         */
        private Date startTime;

        /**
         * 结束时间
         */
        private Date endTime;
    }
}

/**
** 任务执行器的大概实现
**/
public class DefaultTaskService implements TaskService {

    /**
     * 任务执行线程池
     */
    private ThreadPoolExecutor threadPoolExecutor;


    /**
     * 定时调度器
     */
    private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
    
    @Override
    public String execute(Task task) {
        String taskId = null; // 生成任务唯一标识
        //执行任务
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    task.run();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
      
        //定时调度获取任务信息
        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;
    }
}

至此整体的后台实现就已基本完成了,前端到时只需根据任务唯一标识去查询任务执行信息就可以了


原文地址:https://www.cnblogs.com/zhengqun/p/12208763.html