android实现排队任务
相信大家做程序遇到比较多的就是队列,排队问题。对于app上这种问题比较多,比如排队下载,排队发送,并发排队网络请求等等。
要如何自己做好一个这样的功能呢。
下面我给大家将一下我对这一块的理解。
首先在android上,用java编写的程序,需要了解一下队列Queue数据结构(如果有特别的兴趣的可以百度一下,资料很多,我就不粘贴了)。
这次我们主要用的是PriortyBlockingQueue,大家可以理解成一个有优先级排序的阻塞队列排队,注意是可以阻塞的。
具体的PriortyBlockingQueue内部实现是堆,有兴趣的也可以去详细查一下资料。
多的就不说了,很多资料大家都能找到,下面直接看实现代码。
TaskManager.class
public class TaskManager { private PriorityBlockingQueuemQueue; private TaskDispatcher[] mTaskDispatchers; private volatile static TaskManager ourInstance; private final static int MAX_POOL_SIZE = 3; private AtomicInteger mSequenceGenerator = new AtomicInteger(); private TaskManager() { mTaskDispatchers = new TaskDispatchers[MAX_POOL_SIZE]; startTask(); } public static TaskManager getInstance() { if (ourInstance == null) { synchronized (TaskManager.class) { if (ourInstance == null) { ourInstance = new TaskManager(); } } } return ourInstance; } public void stop() { if (mTaskDispatchers != null) { int len = mTaskDispatchers.length; TaskDispatcher dispatcher; for (int i = 0; i < len; i++) { dispatcher = mTaskDispatchers[i]; if (dispatcher != null) { dispatcher.quit(); } } } } public void startTask() { stop(); for (int i = 0; i < mTaskDispatchers.length; i++) { TaskDispatcher dispatcher = new TaskDispatcher(mQueue); mTaskDispatchers[i] = dispatcher; dispatcher.start(); } } public void cancelAll() { stop(); mQueue.clear(); } public void cancelTask(Task task) { if (task != null) { task.cancel(); } } public void addTask(Task task) { task.setSequence(getSequenceNumber()); mQueue.add(downloadTask); }}
首先是任务管理,整个类里面其实代码很简单有几个东西组成:
一个是线程个数的数组TaskDispatchers用来分发和执行Task使用。
MAX_POOL_SIZE 是线程池最大个数这里默认是3个。
AtomicInteger这里只是一个integer的原子操作,大家可以理解就是i++,不过他是线程安全的。
TaskDispatcher.class
public class TaskDispatcher extends Thread { private volatile boolean mQuit = false; private BlockingQueuemQueue; public TaskDispatcher(BlockingQueue mQueue) { this.mQueue = mQueue; } public void quit() { mQuit = true; interrupt(); } @Override public void run() { android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); Task task; while (true) { try { task = mQueue.take(); if (!task.isRunning()) { task.run(); } } catch (InterruptedException e) { if (mQuit) { return; } continue; } } }}
分发任务类,其实主要就是用来运行每一个task使用的,本身自己就是一个无限循环的线程,永远在后台运行。这里其实就是要注意的就是停止线程的方法。因为本身的Queue是一个阻塞的,所以只要在外部调用打断会有catch的错误,通过方法来停止一个当前想取消的一个任务,随后需要一个变量来控制一下循环的结束。
Task.class
public abstract class Task implements Runnable, Comparable{ private Integer mSequence; private String uuid; public enum Priority { LOW, NORMAL, HIGH, IMMEDIATE } public void Task() { uuid = UUID.randomUUID().toString(); } public Priority getPriority() { return Priority.NORMAL; } public void setSequence(Integer sequence) { this.mSequence = sequence; } @Override public int compareTo(Task o) { if(o == null) { return this.mSequence; } if(this.mSequence == null) { this.mSequence = new Integer(0); } if(o.mSequence == null) { o.mSequence = new Integer(0); } Priority left = this.getPriority(); Priority right = o.getPriority(); return left == right ? this.mSequence - o.mSequence : right.ordinal() - left.ordinal(); } @Override public void run() { } public String getUuid() { return uuid; } public void setUuid(String uuid) { this.uuid = uuid; }}
最后一个就是我们的任务了,大家要注意的问题在于Comparable接口,因为刚才说过了,PriorytyBlockingQueue是一个阻塞有优先级的队列,而且在队列里面的类必须实现这个接口,目的是为了让排队在末尾或后面的任务一些需要优先执行的任务可以先执行。
注意:这里没有任务完成回调,需要自己设计,这个在这里就不讲了。
整个队列多线程就搞定了,这个时候如果你想网络请求使用这的话你只需要把自己的网络请求任务类继承Task,实现run方法(这个方法中实现请求的访问和回调)。
最后你只需要在发网络请求的地方调用:如TaskManager.getInstance().addTask(new HttpTask());
就搞定了,整个队列会一直循环执行。
最户提醒一下,在不需要的时候,需要调用一下TaskManager.getInstance().stop();停止所有线程避免造成泄漏。
更多相关文章
- Android的view重绘
- Android(安卓)UI线程和非UI线程
- Android中Volley发送带有Cookie信息的请求
- Android启动service下载失败后stopService,重新启动service下载出
- Android之Handler:实现计时器实例
- Android中线程同步
- Android开发——消息处理传递机制
- 【Android】Handler 中 Looper 死循环为什么不会导致应用卡死的
- Android中AsyncTask的简单总结