這是GCD的第二篇筆記歹苦,接著前一篇來介紹GCD的使用慢逾。
上一篇說了什么是Dispatch Queue及它的兩種形態(tài)醋闭,這篇記錄下GCD的基本用法。
生成隊列:dispatch_queue_create
通過這個函數(shù)可以生成Dispatch Queue缘揪。
//一個Serial Dispatch Queue
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.wang.MySerialDispatchQueue",NULL)义桂;
//一個Concurrent Dispatch Queue
dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create("com.wang.MyConcurrentDispatchQueue"找筝,DISPATCH_QUEUE_CONCURRENT);
第一個參數(shù)可以是NULL慷吊,不過推薦寫個名字袖裕。其作用在于調(diào)試的時候,出現(xiàn)溉瓶,如圖:
第二個參數(shù)是生成Serial Dispatch Queue和Concurrent Dispatch Queue急鳄。
生成Serial時只需將第二個參數(shù)設(shè)置為NULL就可以了谤民。ARC環(huán)境下也無需我們手動釋放了,但非ARC下需要手動釋放:dispatch_release(queue);
前面說過Serial Dispatch Queue只開一個線程疾宏,同時只能執(zhí)行1個追加處理张足。但用dispatch_queue_create函數(shù)可以生成多個Dispatch Queue。這就意味著如果都生成Serial Dispatch Queue坎藐,可以在每一個隊列中都追加任務(wù)为牍,這樣可以開多個線程來執(zhí)行。
比如代碼如下:
dispatch_queue_t queue = dispatch_queue_create("com.wang.MySerialDispatchQueue", NULL);
dispatch_queue_t queue1 = dispatch_queue_create("com.wang.MySerialDispatchQueue1", NULL);
dispatch_queue_t queue2 = dispatch_queue_create("com.wang.MySerialDispatchQueue2", NULL);
dispatch_queue_t queue3 = dispatch_queue_create("com.wang.MySerialDispatchQueue3", NULL);
建4個岩馍,然后追加Log任務(wù)碉咆。結(jié)果如下:
可以看到,每一個Serial Dispatch Queue就開了一個線程蛀恩,這里加上主線程就有5個吟逝。
雖然dispatch_queue_create可以生成多個Dispatch Queue,但是也要注意Serial Dispatch Queue的個數(shù)不要太多赦肋,它和線程是一對一的關(guān)系块攒,如果過多的使用線程,會消耗大量內(nèi)存佃乘,會降低系統(tǒng)的響應(yīng)性能的囱井。并且在多個線程處理更新相同資源的時候會發(fā)生數(shù)據(jù)競爭的。
記錄下《Objective-C高級編程》里所寫:在Serial Dispatch Queue的的生成個數(shù)應(yīng)當(dāng)僅限所必需的數(shù)量趣避。例如更新數(shù)據(jù)庫時1個表生成1個Serial Dispatch Queue庞呕,更新文件時1個文件或是可以分割的1個文件塊生成1個Serial Dispatch Queue。雖然“Serial Dispatch Queue比Concurrent Dispatch Queue能生成更多的線程”程帕,但絕不能激動之下大量生成Serial Dispatch Queue住练。
數(shù)據(jù)競爭問題,如想不發(fā)生而且并行執(zhí)行線程愁拭,就使用Concurrent Dispatch Queue讲逛。
主隊列和全局隊列(Main Dispatch Queue和Global Dispatch Queue)
這兩個隊列是系統(tǒng)本來就提供的隊列,不用再創(chuàng)造了岭埠,能直接將任務(wù)追加到這兩個隊列上執(zhí)行盏混。
主隊列
主隊列是和主線程相關(guān)聯(lián)的隊列,是一個Serial Dispatch Queue惜论。
如果把任務(wù)放到主隊列中進(jìn)行處理许赃,那么不論處理函數(shù)是異步的還是同步的都不會開啟新的線程。
追加到主隊列中的任務(wù)會在主線程中執(zhí)行馆类,因此這里面通常追加一些界面更新的操作混聊。如performSelectorOnMainThread差不多。獲取主隊列的函數(shù)如下:
dispatch_queue_t queue=dispatch_get_main_queue();
主要追加方式:
NSLog(@"這是主線程-----%@",[NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(),^{
NSLog(@"打印線程-%@",[NSThread currentThread]);
});
結(jié)果:
全局隊列
另一個系統(tǒng)提供的是全局隊列:Global Dispatch Queue乾巧,它是Concurrent Dispatch Queue句喜。并且還有4個執(zhí)行優(yōu)先級僵闯,分別是高優(yōu)先級(High Priority)、默認(rèn)優(yōu)先級(Default Priority)藤滥、低優(yōu)先級(Low Priority)鳖粟、后臺優(yōu)先級(Background Priority)。
在向全局隊列追加任務(wù)的時候拙绊,應(yīng)選擇與處理內(nèi)容對應(yīng)的執(zhí)行優(yōu)先級向图。
各優(yōu)先級獲取方法:
//Global高優(yōu)先級
dispatch_queue_t globalHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
//Global默認(rèn)優(yōu)先級
dispatch_queue_t globalDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//Global低優(yōu)先級
dispatch_queue_t globalLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
//Global后臺優(yōu)先級
dispatch_queue_t globalBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
優(yōu)先級順序從高到低。
基本使用
在程序里标沪,就一般使用系統(tǒng)提供的兩個隊列來處理任務(wù)就足夠了榄攀。比如需要在后臺獲取一張網(wǎng)絡(luò)圖片,然后將它顯示到界面上金句,用GCD怎么做檩赢。如下代碼所示:
- (void)viewDidLoad {
[super viewDidLoad];
//獲取全局隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//追加下載圖片任務(wù)
dispatch_async(queue, ^{
NSLog(@"%@",[NSThread currentThread]);
//從網(wǎng)絡(luò)上下載圖片
NSURL *url = [NSURL URLWithString:@"http://ww2.sinaimg.cn/mw690/005ClD7hjw1f29afwpes2j30sg0sgdhx.jpg"];
NSData *data=[NSData dataWithContentsOfURL:url];
UIImage *image=[UIImage imageWithData:data];
NSLog(@"圖片加載完畢");
//回到主線程刷新界面,就是向主隊列中添加任務(wù)
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
NSLog(@"%@",[NSThread currentThread]);
});
});
}
打印結(jié)果:
顯示效果:
OK违寞,GCD的基本使用就是如此贞瞒。