iOS多執行緒的初步研究(八)-- dispatch佇列
GCD程式設計的核心就是dispatch佇列,dispatch block的執行最終都會放進某個佇列中去進行,它類似NSOperationQueue但更復雜也更強大,並且可以巢狀使用。所以說,結合block實現的GCD,把函式閉包(Closure)的特性發揮得淋漓盡致。
dispatch佇列的生成可以有這幾種方式:
1. dispatch_queue_t queue = dispatch_queue_create("com.dispatch.serial", DISPATCH_QUEUE_SERIAL); //生成一個序列佇列,佇列中的block按照先進先出(FIFO)的順序去執行,實際上為單執行緒執行。第一個引數是佇列的名稱,在除錯程式時會非常有用,所有儘量不要重名了。
2. dispatch_queue_t queue = dispatch_queue_create("com.dispatch.concurrent", DISPATCH_QUEUE_CONCURRENT); //生成一個併發執行佇列,block被分發到多個執行緒去執行
3. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //獲得程式程序預設產生的併發佇列,可設定優先順序來選擇高、中、低三個優先順序佇列。由於是系統預設生成的,所以無法呼叫dispatch_resume()和dispatch_suspend()來控制執行繼續或中斷。需要注意的是,三個佇列不代表三個執行緒,可能會有更多的執行緒。併發佇列可以根據實際情況來自動產生合理的執行緒數,也可理解為dispatch佇列實現了一個執行緒池的管理,對於程式邏輯是透明的。
官網文件解釋說共有三個併發佇列,但實際還有一個更低優先順序的佇列,設定優先順序為DISPATCH_QUEUE_PRIORITY_BACKGROUND。Xcode除錯時可以觀察到正在使用的各個dispatch佇列。
4. dispatch_queue_t queue = dispatch_get_main_queue(); //獲得主執行緒的dispatch佇列,實際是一個序列佇列。同樣無法控制主執行緒dispatch佇列的執行繼續或中斷。
接下來我們可以使用dispatch_async或dispatch_sync函式來載入需要執行的block。
dispatch_async(queue, ^{
//block具體程式碼
}); //非同步執行block,函式立即返回
dispatch_sync(queue, ^{
//block具體程式碼
}); //同步執行block,函式不返回,一直等到block執行完畢。編譯器會根據實際情況優化程式碼,所以有時候你會發現block其實還在當前執行緒上執行,並沒用產生新執行緒。
實際程式設計經驗告訴我們,儘可能避免使用dispatch_sync,巢狀使用時還容易引起程式死鎖。
如果queue1是一個序列佇列的話,這段程式碼立即產生死鎖:
dispatch_sync(queue1, ^{
dispatch_sync(queue1, ^{
......
});
......
});
不妨思考下,為什麼下面程式碼也肯定死鎖:
dispatch_sync(dispatch_get_main_queue(), ^{
......
});
那實際運用中,一般可以用dispatch這樣來寫,常見的網路請求資料多執行緒執行模型:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//子執行緒中開始網路請求資料
//更新資料模型
dispatch_sync(dispatch_get_main_queue(), ^{
//在主執行緒中更新UI程式碼
});
});
程式的後臺執行和UI更新程式碼緊湊,程式碼邏輯一目瞭然。
dispatch佇列是執行緒安全的,可以利用序列佇列實現鎖的功能。比如多執行緒寫同一資料庫,需要保持寫入的順序和每次寫入的完整性,簡單地利用序列佇列即可實現:
dispatch_queue_t queue1 = dispatch_queue_create("com.dispatch.writedb", DISPATCH_QUEUE_SERIAL);
- (void)writeDB:(NSData *)data
{
dispatch_async(queue1, ^{
//write database
});
}
下一次呼叫writeDB:必須等到上次呼叫完成後才能進行,保證writeDB:方法是執行緒安全的。
dispatch佇列還實現其它一些常用函式,包括:
void dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t)); //重複執行block,需要注意的是這個方法是同步返回,也就是說等到所有block執行完畢才返回,如需非同步返回則巢狀在dispatch_async中來使用。多個block的執行是否併發或序列執行也依賴queue的是否併發或序列。
void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block); //這個函式可以設定同步執行的block,它會等到在它加入佇列之前的block執行完畢後,才開始執行。在它之後加入佇列的block,則等到這個block執行完畢後才開始執行。
void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block); //同上,除了它是同步返回函式
void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block); //延遲執行block
最後再來看看dispatch佇列的一個很有特色的函式:
void dispatch_set_target_queue(dispatch_object_t object, dispatch_queue_t queue);
它會把需要執行的任務物件指定到不同的佇列中去處理,這個任務物件可以是dispatch佇列,也可以是dispatch源(以後博文會介紹)。而且這個過程可以是動態的,可以實現佇列的動態排程管理等等。比如說有兩個佇列dispatchA和dispatchB,這時把dispatchA指派到dispatchB:
dispatch_set_target_queue(dispatchA, dispatchB);
那麼dispatchA上還未執行的block會在dispatchB上執行。這時如果暫停dispatchA執行:
dispatch_suspend(dispatchA);
則只會暫停dispatchA上原來的block的執行,dispatchB的block則不受影響。而如果暫停dispatchB的執行,則會暫停dispatchA的執行。
這裡只簡單舉個例子,說明dispatch佇列執行的靈活性,在實際應用中你會逐步發掘出它的潛力。
dispatch佇列不支援cancel(取消),沒有實現dispatch_cancel()函式,不像NSOperationQueue,不得不說這是個小小的缺憾。
相關推薦
iOS多執行緒的初步研究(八)-- dispatch佇列
GCD程式設計的核心就是dispatch佇列,dispatch block的執行最終都會放進某個佇列中去進行,它類似NSOperationQueue但更復雜也更強大,並且可以巢狀使用。所以說,結合block實現的GCD,把函式閉包(Closure)的特性發揮得淋漓盡致。 dispatch佇列的生成可以有這
iOS 多執行緒初步研究-NSThread
對於多執行緒的開發,iOS系統提供了多種不同的介面,先談談iOS多執行緒最基礎方面的使用。產生執行緒的方式姑且分兩類,一類是顯式呼叫,另一類是隱式呼叫。 一、顯示呼叫的類為NSThread。一般構造NSThread的執行緒物件可通過兩種方式: 1. 初始化執行緒主方法: [NSThread deta
java多執行緒快速入門(八)
設定執行緒優先順序:join() package com.cppdy; class MyThreadA extends Thread{ MyThreadB b; public MyThreadA(MyThreadB b) { this.b=b; }
Linux多執行緒基礎學習(八)私有資料
/*============================================================================ // Name : thread_privateData.cpp // Author : Ryan // Version
iOS多執行緒的初步研究(十)-- dispatch同步
一、dispatch組(dispatch group) 1. 建立dispatch組 dispatch_group_t group = dispatch_group_create(); 2. 啟動dispatch佇列中的block關聯到group中 dispatch_group_async(group,
iOS多執行緒的初步研究(九)— dispatch源
dispatch源(dispatch source)和RunLoop源概念上有些類似的地方,而且使用起來更簡單。要很好地理解dispatch源,其實把它看成一種特別的生產消費模式。 dispatch源
ios多執行緒初步,主執行緒重新整理UI
去研究一下iOS多執行緒的起因是自己程式裡用了一個等待指示器UIActivityIndicatorView,俗稱小菊花。但是在給頂層ViewController用addsubview加入這個控制元件並使轉動時,螢幕並沒有出現菊花。經過好一番除錯都沒找到原因。去網
iOS 多執行緒使用總結(很實用)
每次準備開始新的航行,總是要複習一遍演算法啊,多執行緒啊,記憶體管理啊之類的理論和應用知識,這次把他們整理成文件,方便以後的學習和不斷的積累進步。 多執行緒給我留下的是痛苦的記憶,當時在上家創業公司的最後階段,就是被Feature Phone上面的多執行緒方案導致bug叢生,搞的焦頭爛額。
多執行緒詳解(二)
多執行緒詳解(二) 在正式介紹執行緒建立的第二種方法之前,我們接著多執行緒詳解(一),講一下:對執行緒的記憶體圖、執行緒的狀態,為下面的學習打下基礎,小夥伴們不要急喲!! 一、多執行緒執行的記憶體圖(ps.博主沒有找到合適的畫圖工具,歡迎大神們貢獻啊) class pers
多執行緒詳解(一)
[多執行緒詳解(一)](http://www.neilx.com) 一、概念準備 1、程序 (1)直譯:正在進行中的程式 (2)解釋:執行一個程式時,會在記憶體中為程式開闢空間,這個空間就是一個程序。 (3)注意:一個程序中不可能沒有執行緒,只有有了執行緒才能執行; 程序只
Linux程式設計 多程序,多執行緒求解PI(圓周率)
題目: 連結 多程序: #include <unistd.h> #include <stdio.h> #include <stdlib.h> #define n 100000000.0 int main() { i
多執行緒學習總結(二)
一、多執行緒帶來的問題 (一)活躍性問題 死鎖:兩個執行緒相互等待對方釋放資源 飢餓: 多執行緒併發時優先順序低的執行緒永遠得不到執行;執行緒被永久阻塞在一個等待進入同步塊的狀態;等待的執行緒永遠不被喚醒 活鎖:活鎖指的是任務或者執行者沒有被阻塞,由於某些條件沒有滿足,導致
多執行緒學習總結(一)
一、程序和執行緒的定義 程序:程序是資源(CPU、記憶體等)分配的基本單位,它是程式執行時的一個例項。程式執行時系統就會建立一個程序,併為它分配資源,然後把該程序放入程序就緒佇列,程序排程器選中它的時候就會為它分配CPU時間,程式開始真正執行。 執行緒:執行緒是程式執行時的最小單位,它是程序
java:多執行緒的基礎(引入)
* 1.什麼是執行緒 * 執行緒是程式執行的一條路徑, 一個程序中可以包含多條執行緒 * 多執行緒併發執行可以提高程式的效率, 可以同時完成多項工作* 2.多執行緒的應用場景 * 紅
java多執行緒快速入門(四)
通過匿名內部類的方法建立多執行緒 package com.cppdy; //通過匿名內部類的方法建立多執行緒 public class ThreadDemo2 { public static void main(String[] args) { new Thread(ne
java多執行緒快速入門(六)
多執行緒應用例項(批量傳送簡訊) 1、建立實體類 package com.cppdy; public class UserEntity { private int id; private String name; public int g
java多執行緒快速入門(七)
什麼是守護執行緒 守護執行緒是為使用者執行緒服務的這麼一個執行緒,主執行緒結束,守護執行緒也結束 package com.cppdy; class MyThread3 extends Thread{ @Override public void run() {
java多執行緒快速入門(九)
多執行緒安全問題(賣火車票案例) package com.cppdy; class MyThread5 implements Runnable{ private Integer ticketCount=100; @Override public void run() {
java多執行緒快速入門(十三)
死鎖產生的原因(必須有兩個執行緒、必須有多個鎖、鎖之間必須有引用的過程) package com.cppdy; class MyThread9 implements Runnable { private Integer ticketCount = 100; private Obje
Java——多執行緒基本使用(四) 執行緒組和執行緒池的使用,工廠設計模式的使用
1.執行緒組的概述和使用 Java中使用ThreadGroup來表示執行緒組,它可以對一批執行緒進行分類管理,Java允許程式直接對執行緒組進行控制。 &n