源码

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 条评论

发表回复

您的电子邮箱地址不会被公开。