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


    背景

     最近一个项目上有这么个功能:数据备份及恢复的任务,可手动终止,并可查看任务的当前执行进度。
     本篇的设计思想是通用的,只不过采用的是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;
        }
    }
    

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


  • 相关阅读:
    IE hasLayout详解
    seajs引入jquery
    jquery实现轮播插件
    CSS视觉格式化模型
    js事件冒泡和事件捕获详解
    你尽力了么===BY cloudsky
    前向否定界定符 python正则表达式不匹配某个字符串 以及无捕获组和命名组(转)
    php safe mode bypass all <转>
    WAF指纹探测及识别技术<freebuf>
    linux集群管理<转>
  • 原文地址:https://www.cnblogs.com/zhengqun/p/12208763.html
Copyright © 2020-2023  润新知