目录
源码
class AbsQueueTaskHelper<T> {
protected final String TAG = this.getClass().getSimpleName();
/**
* 是否有正在执行的任务
*/
private boolean isTaskRunning = false;
private OnTaskActivateListener onTaskActivateListener;
/**
* 记录已经执行的次数
*/
private int alreadyFinishCount = 0;
/**
* 起始时间,用于统计任务耗时时间。
*/
private long startTime;
/**
* 队列任务是否结束
*/
private boolean isFinish = true;
/**
* 这里使用非阻塞队列
*/
private Queue<T> queue = new LinkedList<>();
private static AbsQueueTaskHelper instance = new AbsQueueTaskHelper();
protected AbsQueueTaskHelper(){
isTaskRunning = false;
this.alreadyFinishCount = 0;
this.isFinish = true;
}
public static AbsQueueTaskHelper getInstance(){
return instance;
}
public void init(){
isTaskRunning = false;
this.isFinish = false;
queue.clear();
}
/**
* 将数据加入队列
* @param item
*/
public void join(T item){
queue.offer(item);
activateTask();
}
/**
* 取队列数据执行任务
*/
public void next(){
alreadyFinishCount++;
isTaskRunning = false;
activateTask();
}
/**
* 激活队列任务
*/
private void activateTask(){
if(isTaskRunning == false){
if(queue.size() > 0){
isFinish = false;
T item = queue.poll();
if(onTaskActivateListener != null){
isTaskRunning = true;
if(alreadyFinishCount == 0){
startTime = System.currentTimeMillis();
}
onTaskActivateListener.onTaskActivate(item);
}
}else{
isFinish = true;
}
}else{
// Log.d(TAG,"try to activateTask but there is a task running now");
}
}
public void finish(){
this.isFinish = true;
}
/**
* 用于客户端调用自己的业务
* @param onTaskActivateListener
*/
public void setOnTaskActivateListener(
OnTaskActivateListener onTaskActivateListener) {
this.onTaskActivateListener = onTaskActivateListener;
}
/**
* 监听激活
* @param <T>
*/
public interface OnTaskActivateListener<T> {
void onTaskActivate(T item);
}
public int getAlreadyFinishCount() {
return alreadyFinishCount;
}
public long getUsedTimeMilliSeconds(){
return System.currentTimeMillis() - startTime;
}
public boolean isFinish() {
return isFinish;
}
}
用法
1.实现抽象类
实现AbsQueueTaskHelper类,定义队列元素的泛型。
class WriteLogQueueTaskHelper extends AbsQueueTaskHelper<String> {
private WriteLogQueueTaskHelper() {
super();
}
}
2.初始化实现的工具类
WriteLogQueueTaskHelper.getInstance().init();
3.监听队列元素任务触发
监听队列元素任务触发,队列元素入列的时候,如果没有正在执行的任务会自动触发OnTaskActivateListener方法。
WriteLogQueueTaskHelper.getInstance().setOnTaskActivateListener(new AbsQueueTaskHelper.OnTaskActivateListener<String>() {
@Override
public void onTaskActivate(final String item) {
//一般的下面的代码应该在子线程中执行,这里没有写。
//1、对入列的元素item做一些操作
//2、手动地触发下一个元素的任务执行
WriteLogQueueTaskHelper.getInstance().next();
}
});
4.手动地触发下一个元素的任务执行
在上面的代码中有这样一行代码:
WriteLogQueueTaskHelper.getInstance().next();
在把队列的某个元素的任务处理完毕后,手动调用一下上面的方法以触发队列下一个元素的任务的执行。
5.入列
在数据接收的地方,将数据入列。
WriteLogQueueTaskHelper.getInstance().join(stringBuilder.toString());
工具类的设计初衷与作用
在北京工作的时候,一个项目有段程序的逻辑是这样的:设备发来一个指令,app端就执行相相应的任务。指令A对应任务A,指令B对应任务B...指令N对应任务N。正常的处理流程应该是指令A发送过来,执行任务A,执行完任务A之后再执行任务B...执行完任务N-1再执行任务N。经调试我发现我的同事直接指令X发过来就执行任务X,但是执行任务的同时,可能下一个指令就过来,并发的执行多个任务这样就导致了bug的产生。
于是我设计了这样的一个工具类:保证指令的处理依次进行,拿到指令A后等任务A处理完毕,再去拿指令B处理任务B...拿到指令N执行任务N。
工具类的应用场景:
凡是涉及到类似于队列、严格有序的场景,都可以使用此工具类。如:
1)日志打印
日志打印可能无处不在,不分线程,很容易同时读写文件,造成异常。可以将需要打印的日志入列,然后取一条日志写入本地再取下一条再写入本地,保证有条不紊。
0 条评论