13°

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

背景

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

全部评论: 0

    我有话说: