主要涉及到的概念git
知識點:程序員
任務的執行方式有兩種,隊列有四種,共有8種組合,分別爲:github
dispatch_queue_t queueSerial = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_sync(queueSerial, task);
dispatch_sync(queueSerial, task1);
NSLog(@"end");
複製代碼
當前是在主線程運行,同步執行會阻塞當前線程(主線程),因此end會在執行完task
和task1
以後輸出,安全
dispatch_sync(queueSerial, task);
複製代碼
dispatch_sync
阻塞當前線程(主線程)queueSerial
中插入任務task
task
任務task
任務執行完成解除對當前線程(主線程)的阻塞dispatch_sync(queueSerial, task1); //同理
複製代碼
dispatch_sync
阻塞當前線程(主線程)queueSerial
中插入任務task1
task1
任務task1
任務執行完成解除對當前線程(主線程)的阻塞因此執行順序爲task
->task1
->end
markdown
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.conc", DISPATCH_QUEUE_CONCURRENT);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_sync(queueConcurrent, task);
dispatch_sync(queueConcurrent, task1);
NSLog(@"end");
複製代碼
在當前線程同步執行不管是串行隊列仍是併發隊列任務都是按照順序執行,其結果和 同步執行+串行隊列 一致多線程
//第一個參數是隊列優先級,第二個參數是保留值默認傳0
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_sync(queueGlobal, task);
dispatch_sync(queueGlobal, task1);
NSLog(@"end");
複製代碼
全局隊列本質是併發隊列,其結果和 同步執行+併發隊列 一致併發
dispatch_queue_t queueMain = dispatch_get_main_queue();
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_sync(queueMain, task); //我也是一個任務 記爲 sync1
dispatch_sync(queueMain, task1);
NSLog(@"end");
複製代碼
這種狀況比較特殊,會引發死鎖,其緣由是同步執行語句dispatch_sync(queueMain, task);
自己也是一個任務,咱們記爲 sync1
,sync1
任務是在當前線程(主線程)同步執行的,sync1
任務是向主隊列中添加一個任務task
並在當前線程(主線程)同步執行任務task
,也就是說sync1
任務執行完成的前提是task
任務執行完成。 由於task
任務是在sync1
任務以後插入主隊列的,因此主線程要先執行完sync1
任務纔會去執行task
任務,而sync1
任務執行完成的前提是task
任務執行完成,因此就陷入了死鎖狀態,形成崩潰。app
相似的異步
dispatch_queue_t queueSerial = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
void(^task1)(void) = ^{
NSLog(@"死鎖了嗎");
};
void(^task2)(void) = ^{
dispatch_sync(queueSerial, task1);
};
//開闢子線程,並向串行隊列queueSerial中添加任務 task2
dispatch_async(queueSerial, task2);
複製代碼
dispatch_async(queueSerial, task2);
自己也是一個任務記爲sync1
,但不一樣的是sync1
是在當前線程(主線程)執行,sync1
任務執行結果是向串行隊列queueSerial
中添加任務task2
並開闢子線程執行task2
,任務task2
是向串行隊列queueSerial
中添加任務task1
並在當前線程同步執行任務task1
,也就是說task2
任務執行完成的前提是task1
任務執行完成,由於task2
任務比task1
任務先添加到串行隊列queueSerial
,因此任務task2
執行完成以後纔會去執行tasi1
,async
注意:異步執行+串行隊列只會開闢一條子線程
dispatch_queue_t queueSerial = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_async(queueSerial, task); //我也是一個任務 記爲 sync1
dispatch_async(queueSerial, task1);
NSLog(@"end");
複製代碼
將task
和task1
分別添加到串行隊列queueSerial
,開闢一條子線程順序執行隊列queueSerial
中的任務,由於end是在主線程輸出的,因此輸出順序爲end
->task
->task1
,由於異步執行+串行隊列只開闢一條子線程,因此task
和task1
在同一個線程中執行
這個時候理論上能夠開闢多個子線程了
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.conc", DISPATCH_QUEUE_CONCURRENT);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_async(queueConcurrent, task);
dispatch_async(queueConcurrent, task1);
NSLog(@"end");
複製代碼
由於task
和task1
有可能不是在同一個字線程執行的,兩個任務不必定誰先結束執行,因此不能肯定task
和task1
誰先輸出,由於end是在主線程輸出的,因此先輸出end
dispatch_queue_t queueMain = dispatch_get_main_queue();
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_async(queueMain, task);
dispatch_async(queueMain, task1);
複製代碼
主隊列本質上也是一個串行隊列,因此按照順序執行task
->task1
,另外祝隊列任務只能在主線程執行,因此task
和task1
都在主線程執行
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
void(^task)(void) = ^{
NSLog(@"task--%@",[NSThread currentThread]);
};
void(^task1)(void) = ^{
NSLog(@"task1--%@",[NSThread currentThread]);
};
dispatch_async(queueGlobal, task);
dispatch_async(queueGlobal, task1);
複製代碼
全局隊列是一個併發隊列,因此有能力開闢多個子線程,固然也可能在一個子線程中去執行
咱們須要將一些耗時任務放在子線程,執行完畢以後再回到主線程刷新頁面
dispatch_queue_t queueMain = dispatch_get_main_queue();
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_async(queueGlobal, ^{
sleep(3);//模擬耗時操做
dispatch_async(queueMain, ^{
NSLog(@"主線程");
});
});
複製代碼
在《程序員的自我修養:連接、裝載與庫。》一書的過分優化部分有這麼一段話
「CPU的亂序執行能力讓咱們對多線程的安全保障的努力變得異常困難。所以要保證線程安全,阻止CPU換序是必需的。遺憾的是,如今並不存在可移植的阻止換序的方法。一般狀況下是調用CPU提供的一條指令,這條指令經常被稱爲barrier。一條barrier指令會阻止CPU將該指令以前的指令交換到barrier以後,反之亦然。換句話說,barrier指令的做用相似於一個攔水壩,阻止換序「穿透」這個大壩。」
摘錄來自: 俞甲子 石凡 潘愛民. 「程序員的自我修養:連接、裝載與庫。」 Apple Books.
爲了保證某些操做的原子性,CUP提供了barrier
指令,用來保證在barrier
指令以前的指令執行完成以後纔會執行barrier
以後的指令,dispatch_barrier_async
的意思大致也是如此,在異步執行併發隊列中保證先執行完dispatch_barrier_async
以前的任務,而後再執行dispatch_barrier_async
中的任務,其次執行dispatch_barrier_async
以後的任務
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_async(queueGlobal, ^{
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_async(queueGlobal, ^{
sleep(2);
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_barrier_async(queueGlobal, ^{
NSLog(@"barrier--%@",[NSThread currentThread]);
});
dispatch_async(queueGlobal, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_async(queueGlobal, ^{
NSLog(@"4--%@",[NSThread currentThread]);
});
複製代碼
全局隊列是一個併發隊列,盲猜這裏應該先打印出來1
和2
,而後執行barrier
,而後隨機打出3
和4
,可是實際上呢
barrier
彷佛跟dispatch_async
同樣,並無起到什麼做用,查了一番資料終於在官方文檔找到正解 dispatch_barrier_async
若是本身經過dispatch_queue_create
建立併發隊列沒問題,若是是一個串行隊列或者全局併發隊列那麼和dispatch_async
效果同樣同樣的,咱們換成本身建立的併發隊列
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.conc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queueConcurrent, ^{
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
sleep(2);
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_barrier_async(queueConcurrent, ^{
NSLog(@"barrier--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
NSLog(@"4--%@",[NSThread currentThread]);
});
NSLog(@"end");
複製代碼
從結果看到dispatch_barrier_async
並無阻塞當前線程,而只是阻塞了當前異步隊列其餘任務的執行,官方文檔也證明了這一點
咱們先去官方文檔看一下dispatch_barrier_sync
一方面dispatch_barrier_sync
會阻塞當前線程,另外一方面可能形成死鎖deadlock
,咱們驗證一下
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.conc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queueConcurrent, ^{
sleep(2);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_barrier_sync(queueConcurrent, ^{
NSLog(@"barrier--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
NSLog(@"4--%@",[NSThread currentThread]);
});
NSLog(@"end");
複製代碼
咱們看到dispatch_barrier_sync
確實阻塞了當前線程,end
是在dispatch_barrier_sync
以後輸出的
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.conc", DISPATCH_QUEUE_CONCURRENT);
dispatch_barrier_sync(queueConcurrent, ^{
NSLog(@"barrier--%@",[NSThread currentThread]);
dispatch_sync(queueConcurrent, ^{
NSLog(@"%@",[NSThread currentThread]);
});
});
複製代碼
不知道這是否是文檔中所說的Calling this function and targeting the current queue results in deadlock.
反正實現了deadlock
效果
另外文檔提到了Block_copy
我從源碼看到確實dispatch_barrier_async
調用了_dispatch_Block_copy
而dispatch_barrier_sync
是沒有copy,這多是由於dispatch_barrier_sync
阻塞線程後面代碼不執行,而dispatch_barrier_async
沒有阻塞線程,那麼後面就可能對函數體修改????因此拷貝一份這裏留下問好
2秒以後將任務添加到主隊列,具體何時執行還要看CUP的調度
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), mainQueue, ^{
//2秒以後將任務添加到主隊列,具體何時執行還要看CUP的調度
NSLog(@"執行了");
});
複製代碼
實現單例
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//單例
});
複製代碼
更多內容能夠看一下# iOS多線程之dispatch_once剖析
先來看一下文檔dispatch_apply
能夠看到dispatch_apply
和可重入且安全的併發隊列能夠實現高效的遍歷操做,若是是一個串行隊列那麼就體現不出來他的高效之處了
dispatch_apply(10, queueGlobal, ^(size_t index) {
NSLog(@"%zd--%@",index,[NSThread currentThread]);
});
NSLog(@"end");
複製代碼
dispatch_apply
會利用多個線程來遍歷,不光是子線程,還能夠調用主線程,另外他還會阻塞當前線程
dispatch_group
做爲一個單元監控一組任務。你能夠將一組任務放到一個組裏經過dispatch_group
同步他們的行爲。你能夠將這些任務放在組裏之後在同一個隊列或者不一樣的隊列異步執行,能夠在不阻塞當前線程的狀況下監聽這些異步任務執行完畢,也能夠阻塞當前線程等待這些任務完成。
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queueGlobal, ^{
sleep(2);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
sleep(1);
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_group_notify(group, queueGlobal, ^{
NSLog(@"notify--%@",[NSThread currentThread]);
});
NSLog(@"end--%@",[NSThread currentThread]);
複製代碼
dispatch_group_notify
並無阻塞當前線程,他是在當前組的其餘隊列都執行完成以後再執行,咱們能夠將dispatch_group_notify
任務放在主隊列執行,這就實現了回調主線程的功能
dispatch_queue_t queueSerial = dispatch_queue_create("com.serial", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queueMain = dispatch_get_main_queue();
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queueGlobal, ^{
sleep(2);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueSerial, ^{
sleep(1);
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueSerial, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_group_notify(group, queueMain, ^{
NSLog(@"notify--%@",[NSThread currentThread]);
});
NSLog(@"end--%@",[NSThread currentThread]);
複製代碼
阻塞當前線程,等待組內任務都執行完成纔會繼續執行
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queueGlobal, ^{
sleep(2);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
sleep(1);
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"end--%@",[NSThread currentThread]);
複製代碼
直到前面三個任務都執行完成纔會打印end,固然也能夠將阻塞的超時時間設置小一些,即便前面任務沒有完成,可是時間到了也會繼續執行
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queueGlobal, ^{
sleep(3);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
sleep(1);
NSLog(@"2--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queueGlobal, ^{
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2*NSEC_PER_SEC)));
NSLog(@"end--%@",[NSThread currentThread]);
複製代碼
dispatch_group_async
內部也是經過dispatch_group_enter
和dispatch_group_leave
來實現的
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, 0);
dispatch_group_enter(group);
dispatch_async(queueGlobal, ^{
sleep(3);
NSLog(@"1--%@",[NSThread currentThread]);
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queueGlobal, ^{
sleep(1);
NSLog(@"2--%@",[NSThread currentThread]);
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queueGlobal, ^{
NSLog(@"3--%@",[NSThread currentThread]);
dispatch_group_leave(group);
});
dispatch_group_notify(group, queueGlobal, ^{
NSLog(@"notify--%@",[NSThread currentThread]);
});
NSLog(@"end--%@",[NSThread currentThread]);
複製代碼
實現了和dispatch_group_async
同樣的效果
在開發中常常須要線程同步,那麼信號量是一個很好的選擇,dispatch_semaphore_signal
信號量+1,dispatch_semaphore_wait
信號量-1,若是信號量小於0那麼阻塞當前線程,能夠設置阻塞的超時時間
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(queueGlobal, ^{
sleep(3);//耗時操做
NSLog(@"1--%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);//信號量+1
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//信號量-1
dispatch_async(queueMain, ^{
NSLog(@"主線程");
});
NSLog(@"end--%@",[NSThread currentThread]);
複製代碼
多線程訪問同一個數據有可能形成數據不安全,例如
__block int i = 5;
while (i>0) {
dispatch_async(queueGlobal, ^{
i--;
NSLog(@"%d--%@",i,[NSThread currentThread]);
});
}
複製代碼
因爲多線程同時修改i
致使結果和預期出現了很大的出入,甚至NSLog
函數的打印都出問題了😂,經過信號量能夠解決這個問題
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block int i = 5;
while (i>0) {
dispatch_async(queueGlobal, ^{
i--;
NSLog(@"%d--%@",i,[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
複製代碼
這個時候咱們看到結果按照預期輸出了,由於信號量控制最多隻有一個線程能夠訪問變量i
(不必定是同一個線程,但同一時間最多隻能有一個線程訪問)
dispatch_set_target_queue
有兩個做用一是改變隊列優先級,二是讓多個串行隊列之間也能串行地執行任務。
咱們前邊所學的方法都是控制隊列內部的任務的操做順序,可是不一樣隊列之間是沒有依賴關係的,假如咱們把A任務放在自定義串行隊列serialQueueA中,把B任務放在自定義併發隊列conQueueB中,那麼咱們不知道任務A和任務B的前後執行順序,有了dispatch_set_target_queue
咱們能夠利用其改變隊列優先級的做用實現優先隊列
dispatch_queue_create
建立的隊列,不管是串行仍是併發,其優先級都是 DISPATCH_QUEUE_PRIORITY_DEFAULT
,使用 dispatch_set_target_queue
能夠改變隊列優先級,注意改變的是優先調度開始順序,而不是結束順序,先被調度的不必定先結束執行
dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue3 = dispatch_queue_create("serialQueue3", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue4 = dispatch_queue_create("serialQueue4", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue5 = dispatch_queue_create("serialQueue5", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue6 = dispatch_queue_create("serialQueue6", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue7 = dispatch_queue_create("serialQueue7", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue8 = dispatch_queue_create("serialQueue8", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue1, ^{
NSLog(@"taskA");
});
dispatch_async(serialQueue2, ^{
NSLog(@"taskB");
});
dispatch_async(serialQueue3, ^{
NSLog(@"taskC");
});
dispatch_async(serialQueue4, ^{
NSLog(@"taskD");
});
dispatch_async(serialQueue5, ^{
NSLog(@"taskE");
});
dispatch_async(serialQueue6, ^{
NSLog(@"taskF");
});
dispatch_async(serialQueue7, ^{
NSLog(@"taskG");
});
dispatch_async(serialQueue8, ^{
NSLog(@"taskH");
});
複製代碼
這個時候咱們不能肯定ABCDEFGH誰先執行,簡單修改一下
dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue3 = dispatch_queue_create("serialQueue3", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue4 = dispatch_queue_create("serialQueue4", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue5 = dispatch_queue_create("serialQueue5", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue6 = dispatch_queue_create("serialQueue6", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue7 = dispatch_queue_create("serialQueue7", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue8 = dispatch_queue_create("serialQueue8", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t globalQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(serialQueue2, globalQueueLow);
dispatch_async(serialQueue1, ^{
NSLog(@"taskA");
});
dispatch_async(serialQueue2, ^{
NSLog(@"taskB");
});
dispatch_async(serialQueue3, ^{
NSLog(@"taskC");
});
dispatch_async(serialQueue4, ^{
NSLog(@"taskD");
});
dispatch_async(serialQueue5, ^{
NSLog(@"taskE");
});
dispatch_async(serialQueue6, ^{
NSLog(@"taskF");
});
dispatch_async(serialQueue7, ^{
NSLog(@"taskG");
});
dispatch_async(serialQueue8, ^{
NSLog(@"taskH");
});
複製代碼
咱們增長了兩行代碼
dispatch_queue_t globalQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(serialQueue2, globalQueueLow);
複製代碼
網上看了好多例子都是到此爲止,以致於我任務只是由於我給globalQueueLow
設置的優先級爲DISPATCH_QUEUE_PRIORITY_BACKGROUND
因此serialQueue2
的優先級才筆另外幾個串行隊列低,若是我設置優先級爲DISPATCH_QUEUE_PRIORITY_HIGH
那麼隊列就會優先調度
dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue3 = dispatch_queue_create("serialQueue3", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue4 = dispatch_queue_create("serialQueue4", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue5 = dispatch_queue_create("serialQueue5", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue6 = dispatch_queue_create("serialQueue6", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue7 = dispatch_queue_create("serialQueue7", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue8 = dispatch_queue_create("serialQueue8", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t globalQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_queue_t globalQueueHight = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_set_target_queue(serialQueue2, globalQueueLow);
dispatch_set_target_queue(serialQueue3, globalQueueHight);
dispatch_async(serialQueue1, ^{
NSLog(@"taskA");
});
dispatch_async(serialQueue2, ^{
NSLog(@"taskB");
});
dispatch_async(serialQueue3, ^{
NSLog(@"taskC");
});
dispatch_async(serialQueue4, ^{
NSLog(@"taskD");
});
dispatch_async(serialQueue5, ^{
NSLog(@"taskE");
});
dispatch_async(serialQueue6, ^{
NSLog(@"taskF");
});
dispatch_async(serialQueue7, ^{
NSLog(@"taskG");
});
dispatch_async(serialQueue8, ^{
NSLog(@"taskH");
});
複製代碼
多運行幾回咱們發現設置DISPATCH_QUEUE_PRIORITY_HIGH
優先級以後串行隊列serialQueue3
並無比其餘優先級高,而僅僅比serialQueue2
高了而已,咱們前邊也說過,這種優先級高僅僅是開始調度的優先級高,而不是結束調度的優先級,若是咱們給任務A設置一個耗時任務就能夠驗證
dispatch_async(serialQueue1, ^{
int a=0;
for (int i=0; i<1000000; i++) {
a++;
}
NSLog(@"%d-taskA",a);
});
複製代碼
這時A並無先結束執行,BC也沒有最後結束執行
若是咱們設置
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_set_target_queue(serialQueue3, mainQueue);
複製代碼
這個時候是否是serialQueue3
的優先級會不會很高呢,其實並無
看了官方文檔也是很難理解dispatch_set_target_queue,我我的理解是若是經過dispatch_set_target_queue
設置隊列優先級的這些隊列他們都成了二級公民,依賴於同一個隊列的子隊列之間能夠經過優先級來設置,可是他們的優先級都要比沒有設置過優先級的隊列優先級要低了
咱們可使用dispatch_set_target_queue
+dispatch_suspend/dispatch_resume
實現一個優先隊列
dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(serialQueue1, serialQueue2);
dispatch_async(serialQueue1, ^{
NSLog(@"taskA");
});
dispatch_suspend(serialQueue1);
dispatch_async(serialQueue2, ^{
NSLog(@"taskB");
dispatch_resume(serialQueue1);
});
dispatch_async(serialQueue1, ^{
NSLog(@"taskC");
});
複製代碼