美文网首页
android-线程管理-TaskHelper

android-线程管理-TaskHelper

作者: ihu11 | 来源:发表于2019-10-17 14:37 被阅读0次

    以前线程总是使用new Thread().start()这种方式,或者使用线程池ThreadPoolExecutor管理,但是线程池只能控制数量,无法控制逻辑,各种线程之间的逻辑关系和顺序等

    所以我封装了一个线程管理的类TaskHelper

    TaskHelper主要功能
    1.很多线程集中管理起来使用单线程多任务模式简化逻辑,特别是网络线程
    2.串行的执行方式,可以在不同的类里创建任务并且排队执行,非常方便的管理了线程,例如多同一个文件的io操作,简单的处理
    3.不同id的线程可以通过join来管理顺序,简化了很多操作,优化项目结构

    TaskHelper 实现代码

    import android.os.Process;
    import android.util.Log;
    import android.util.SparseArray;
    
    import java.util.Queue;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.TimeUnit;
    
    public class TaskHelper {
        private final static String TAG = "TaskHelper";
        private SparseArray<SingleTask> helperArray;
        private volatile static TaskHelper instance;
    
        public static TaskHelper getInstance() {
            if (instance == null) {
                synchronized (TaskHelper.class) {
                    if (instance == null) {
                        instance = new TaskHelper();
                    }
                }
            }
            return instance;
        }
    
        private TaskHelper() {
            if (helperArray == null) {
                helperArray = new SparseArray<SingleTask>();
            }
        }
    
        public static SingleTask getTask(int taskId) {
            TaskHelper helper = getInstance();
            SingleTask task;
            synchronized (helper.helperArray) {
                task = helper.helperArray.get(taskId);
                if (task == null) {
                    task = new SingleTask(taskId);
                    helper.helperArray.put(taskId, task);
                }
            }
            return task;
        }
    
        public void cancel() {
            synchronized (helperArray) {
                int size = helperArray.size();
                for (int i = 0; i < size; i++) {
                    SingleTask task = helperArray.valueAt(i);
                    task.cancel();
                }
                helperArray.clear();
            }
            instance = null;
        }
    
        public void cancel(int taskId) {
            SingleTask task = null;
            synchronized (helperArray) {
                task = helperArray.get(taskId);
                if (task != null) {
                    task.cancel();
                    helperArray.remove(taskId);
                }
            }
        }
    
        public static class SingleTask {
            private BlockingQueue<Runnable> queue;
            private boolean isRun = false;
            private int taskId;
            private final Object lock = new Object();
            private Thread mThread;
    
            private SingleTask(int taskId) {
                this.taskId = taskId;
                queue = new LinkedBlockingQueue<Runnable>();
            }
    
            public boolean contains(String runnableName) {
                for (Runnable r : queue) {
                    if (r.getClass().getName().equals(runnableName)) {
                        return true;
                    }
                }
                return false;
            }
    
            public void addTaskAndRun(Runnable runnable) {
                int size = queue.size();
                queue.add(runnable);
                start();
            }
    
            public SingleTask addTask(Runnable runnable) {
                queue.add(runnable);
                return this;
            }
    
            public void join() {
                boolean b;
                synchronized (lock) {
                    b = isRun;
                }
                if (b) {
                    try {
                        mThread.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            public void cancel() {
                queue.clear();
            }
    
            public void start() {
                synchronized (lock) {
                    if (isRun) {
                        return;
                    }
                    isRun = true;
                    mThread = new Thread() {
                        public void run() {
                            Runnable runnable;
                            try {
                                while (isRun
                                        && (runnable = queue.poll(200,
                                        TimeUnit.MILLISECONDS)) != null) {
                                    Log.i(TAG, "run task name:"
                                            + runnable.getClass().getName() + taskId);
                                    try {
                                        runnable.run();
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
    
                            isRun = false;
                            TaskHelper.getInstance().cancel(taskId);
                        }
                    };
                    mThread.setPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    mThread.start();
                }
            }
        }
    }
    
    可以创建一个taskId生成器,统一管理所有的taskId
    public class TaskIdFactory {
        private static int id = 0;
    
        public static int gen() {
            int newId;
            synchronized (TaskIdFactory.class) {
                if (id == Integer.MAX_VALUE - 1) {
                    id = 0;
                }
                ++id;
                newId = id;
            }
            return newId;
        }
    }
    

    使用方法

    1.运行线程
    TaskHelper.getTask(TaskIdFactory.gen()).addTaskAndRun(new Runnable() {
                @Override
                public void run() {
                    //TODO
                }
            });
    
    2.单线程模式
    int taskId = TaskIdFactory.gen();
    TaskHelper.getTask(taskId).addTaskAndRun(new Runnable() {
                @Override
                public void run() {
                    //任务1
                }
            });
    TaskHelper.getTask(taskId).addTaskAndRun(new Runnable() {
                @Override
                public void run() {
                    //任务2
                }
            });
    

    当任务1和任务2的taskId相同时,任务1和任务2就会按顺序排队运行

    3.如果当你在某个地方运行了很多个串联线程,然后又退出了这个界面,就可以使用
    TaskHelper.getTask(taskId).cancel();
    

    停止该线程,使排在队列后面没有运行的任务释放掉,不会再运行了。

    4.如果退出了应用,则可以直接关闭所有任务
    TaskHelper.getInstance().cancel();
    
    5.两个线程直接的顺序管理,例如你的下一个界面要显示的数据要依赖任务的结果,但是任务不是在这个页面启动的。

    比如,我做一个应用商店的时候,首页要显示需要更新的应用数量,就需要在首页去请求更新应用数据,但是二级页面需要更新的应用数据也依赖这个结果。如果打开二级页面的时候这个结果还没返回,就可以使用TaskHelper的线程join,来完成这个功能。这里没必要去启动Service实现那么麻烦,直接在首页使用

    TaskHelper.getTask(taskId1).addTaskAndRun(new Runnable() {
                @Override
                public void run() {
                    //请求数据并保存
                }
            });
    

    然后二级页面启动一个新的任务去等待结果

    TaskHelper.getTask(taskId2).addTaskAndRun(new Runnable() {
                @Override
                public void run() {
                    TaskHelper.getTask(taskId1).join();
                    //读取task1里获取的数据
                }
            });
    

    相关文章

      网友评论

          本文标题:android-线程管理-TaskHelper

          本文链接:https://www.haomeiwen.com/subject/kdwmmctx.html