如何设计可手动终止及查看当前进度的任务
背景
最近一个项目上有这么个功能:数据备份及恢复的任务,可手动终止,并可查看任务的当前执行进度。
本篇的设计思想是通用的,只不过采用的是java语言实现
思考
暂且不谈数据备份及恢复如何实现,这里只是大概介绍下通用任务的实现
任务如何进行终止
所有的代码都是运行在一个线程中的,所以想办法终止正在运行中的线程就可以了.
具体的实现方式:定义一个开关变量来进行控制就可以了.
private volatile boolean on = true;
public void run(){
while(on && hastNextDataToDeal()){
//执行相关业务代码
}
}
public void stop(){
on = false;
}
如何查看获取当前的执行进度
-
获取总体的需要进行处理的记录数
这里说的记录数是一个很泛的概念,比如数据备份这块,可以把它理解为数据库表的数量
-
每条记录处理完毕后,当前已处理的记录数+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;
}
}
至此整体的后台实现就已基本完成了,前端到时只需根据任务唯一标识
去查询任务执行信息就可以了