Telegram开源项目之DispatchQueue
DispatchQueue介绍
在特定的线程(单线程)下的任务队列。
DispatchQueue作用
串行执行耗时的或者涉及网络操作的任务(不好在主线程执行的任务)
例如:数据库读写任务,由于sqlite数据库不支持多线程同时操作,所以顺序执行数据库任务才是安全的,但数据库操作不好放在主线程中执行,所以就需要一个针对单个线程的串行任务队列,在这个线程中顺序执行数据库操作。
DispatchQueue分析
Android系统中Handler是个消息,任务分发的组件,并且Handler的任务执行也是在单个线程中顺序执行的。所以可以使用Handler来接受并处理Runnable任务。
但是在非主线程中创建Handler时并不会自动创建消息队列和进行消息循环处理。所以需要手动创建消息队列和进行消息循环处理。
由于创建Handler和创建消息队列的任务是在线程中执行的,为了保证对Handler的操作在Handler创建完成后,所以需要进行同步处理,这里使用了CountDownLatch(计数减小锁,同步辅助工具)让所有访问Handler的线程等待直到计数为0的时候开始执行。
DispatchQueue代码
/**
* 任务:在特定的线程(单线程)下循序执行任务,做一个先来先执行的任务队列
* 任务分发队列:Handler在指定的线程下进行任务分发,处理。
* Hander的任务是循序执行,单线程。
*/
public class DispatchQueue extends Thread {
private volatile Handler handler = null;
//作用:创建指定线程下的Handler并创建指定的消息队列好和消息循环之前保证添加的任务等待到创建成功后再添加。
private CountDownLatch syncLatch = new CountDownLatch(1);
/**
*
* @param threadName 任务队列所在的线程名
*/
public DispatchQueue(final String threadName) {
setName(threadName);
start();
}
private void sendMessage(Message msg, int delay) {
try {
syncLatch.await();
if (delay <= 0) {
handler.sendMessage(msg);
} else {
handler.sendMessageDelayed(msg, delay);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
/**
* 取消任务
* @param runnable
*/
public void cancelRunnable(Runnable runnable) {
try {
syncLatch.await();
handler.removeCallbacks(runnable);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
/**
* 立刻添加顺序执行的任务
* @param runnable
*/
public void postRunnable(Runnable runnable) {
postRunnable(runnable, 0);
}
/**
* 延时添加顺序执行的任务
* @param runnable
*/
public void postRunnable(Runnable runnable, long delay) {
try {
syncLatch.await();
if (delay <= 0) {
handler.post(runnable);
} else {
handler.postDelayed(runnable, delay);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
/**
* 清空任务队列
*/
public void cleanupQueue() {
try {
syncLatch.await();
handler.removeCallbacksAndMessages(null);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
@Override
public void run() {
Looper.prepare();
handler = new Handler();
syncLatch.countDown();
Looper.loop();//做的操作是个死循环,线程才不会结束。
}
}
DispatchQueue使用示例
public class TestActivity extends Activity {
public static class DemoTask implements Runnable{
int index;
public DemoTask (int index){
this.index= index;
}
@Override
public void run() {
String tag = Thread.currentThread().getName();
Log.e(tag ," 第 "+index+"任务开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(tag ," 第 "+index+"任务完成");
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DispatchQueue dispatchQueue = new DispatchQueue("线程队列演示");
for (int i = 0; i < 10; i++) {
DemoTask demoTask = new DemoTask (i);
dispatchQueue.postRunnable(loveTask);
}
}
}