DispatchQueue介紹
在特定的線程(單線程)下串行執行的任務隊列
DispatchQueue作用
在特定的線程中串行執行耗時的或者涉及網絡操作的任務
比如數據庫操作,Android的sqlite數據庫不支持併發操作,又不好在主線程中執行,所以在線程中串行執行對數據庫的操作是安全的且不會阻塞主線程的。
DispatchQueue代碼
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代碼分析
Android中的Handler是用於分發消息和任務的組件,並且是工作在單個線程中,所以任務執行時串行執行的。
在線程中創建的Handler是不會自動創建消息隊列和進行消息循環操作的,所以需要手動創建消息隊列和進行消息循環。
由於創建Handler是在線程中進行的,所以需要對添加任務到隊列和創建Handler的任務進行同步,確保添加任務的線程在創建Handler線程之後,所以使用CountDownLatch (計數減少鎖)對線程進行同步。
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(demoTask);
}
}
}