多線程(2) - iOS關(guān)于線程調(diào)度的三種方式之GCD GCD(鏈接:http://blog.csdn.net/linzhiji/article/details/6863972) 一 概念和理解 Grand Central Dispatch(多線程的優(yōu)化技術(shù))GCD 是一套底層API,,基于C語言開發(fā)的多線程機制,提供了新的模式編寫并發(fā)執(zhí)行的程序,。 特點: 1.允許將一個程序切分為多個單一任務(wù),,然后提交到工作隊列中并發(fā)或者串行地執(zhí)行 2.為多核的并行運算提出了解決方案,自動合理的利用CPU內(nèi)核(比如雙核,,四核) 3.自動的管理線程的生命周期(創(chuàng)建線程,、調(diào)度任務(wù)、銷毀線程),,完全不需要我們管理,,只需要告訴它任務(wù)是什么就行 4.配合Block,使得使用起來更加方便靈活
2.什么是Queue隊列,? GCD使用了隊列的概念,,解決了NSThread難于管理的問題,隊列實際上就是數(shù)組的概念,,通常我們把要執(zhí)行的任務(wù)放到隊列中管理 特點: 1.按順序執(zhí)行,,先進先出 2.可以管理多線程,管理并發(fā)的任務(wù),,設(shè)置主線程 3.GCD的隊列是任務(wù)的隊列,,而不是線程的隊列
3.什么是任務(wù)? 任務(wù)即操作:你想要干什么,,說白了就是一段代碼,,在GCD中,任務(wù)就是一個block 任務(wù)的兩種執(zhí)行方式: 同步執(zhí)行:只要是同步任務(wù),,都會在當(dāng)前的線程執(zhí)行,,不會另開線程 異步執(zhí)行:只要是異步任務(wù),都會開啟新線程,,在開啟的線程中執(zhí)行 4.什么是串行隊列,? 依次完成每一任務(wù) 5.什么是并行隊列? 好像所有的任務(wù)都是在同一時間執(zhí)行的 6.都有哪些隊列,? Main Queue(主隊列,,串行),;全局隊列(Global Queue),;自己創(chuàng)建的隊列(Queue) 從上面的概念以及gcd所解決的問題來看,使用GCD的時候就要開始轉(zhuǎn)變觀念了?,F(xiàn)在我們需要考慮的只是任務(wù),,隊列,隊列間同步或異步的關(guān)系了,。而不是考慮怎么開辟線程,,怎么管理線程,,所有關(guān)于線程的東西,我們都不需要考慮,。整個程序完全就是由隊列來自動管理了,。首先,整個程序是由全局隊列來管理,,然后UI的刷新是由mainqueue管理,,我們可以將我們的任務(wù)放到我們創(chuàng)建的隊列中去,也可以放在主隊列中,,也可以放在全局隊列中,。 舉個例子:現(xiàn)在我們要從網(wǎng)絡(luò)上下載一張圖片,可以直接將任務(wù)放到主隊列中去執(zhí)行,,但是這樣會出項一個問題,,因為主隊列是處理和UI相關(guān)的任務(wù)的,所以在創(chuàng)建(或者刷新)UI的時候,,界面就會卡住,,直到這張圖片現(xiàn)在完畢。所以一般的做法是首先獲取全局隊列,,然后在全局隊列中植入下載圖片的代碼,,在下完成后,將圖片刷回UI,也就是主隊列,。至于圖片什么時候下載完畢,,怎么開辟線程,我們都不需要管,。需要做的就是處理代碼邏輯就行,。以下是使用GCD下載圖片的代碼 + (void)SL_setImageView:(UIImageView *)imageView url:(NSString *)url { //對應(yīng)全局隊列開啟一個異步任務(wù) dispatch_async(dispatch_get_global_queue(0, 0), ^{ //下載圖片數(shù)據(jù) NSURL *imageURL = [NSURL URLWithString:url]; NSData *data = [NSData dataWithContentsOfURL:imageURL]; UIImage *image = [UIImage imageWithData:data]; //刷新ImageView (回調(diào)主線程) dispatch_async(dispatch_get_main_queue(), ^{ imageView.image = image; }); }); } 關(guān)于容易混淆概念的區(qū)分:
1, 同步,,異步,,串行,并發(fā)
同步和異步代表會不會開辟新的線程,。串行和并發(fā)代表任務(wù)執(zhí)行的方式,。
同步串行和同步并發(fā),任務(wù)執(zhí)行的方式是一樣的,。沒有區(qū)別,,因為沒有開辟新的線程,所有的任務(wù)都是在一條線程里面執(zhí)行,。
異步串行和異步并發(fā),,任務(wù)執(zhí)行的方式是有區(qū)別的,異步串行會開辟一條新的線程,隊列中所有任務(wù)按照添加的順序一個一個執(zhí)行,,異步并發(fā)會開辟多條線程,,至于具體開辟多少條線程,是由系統(tǒng)決定的,,但是所有的任務(wù)好像就是同時執(zhí)行的一樣,。
開辟隊列的方法: dispatch_queue_t myQueue = dispatch_queue_create("MyQueue", NULL); /**
參數(shù)1:標簽,用于區(qū)分隊列 參數(shù)2:隊列的類型,,表示這個隊列是串行隊列還是并發(fā)隊列NUll表示串行隊列,, DISPATCH_QUEUE_CONCURRENT表示并發(fā)隊列 */ 執(zhí)行隊列的方法 異步執(zhí)行 dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>) 同步執(zhí)行 dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)
二,主隊列
主隊列:專門負責(zé)調(diào)度主線程度的任務(wù),,沒有辦法開辟新的線程,。所以,在主隊列下的任務(wù)不管是異步任務(wù)還是同步任務(wù)都不會開辟線程,,任務(wù)只會在主線程順序執(zhí)行,。 主隊列異步任務(wù):現(xiàn)將任務(wù)放在主隊列中,但是不是馬上執(zhí)行,,等到主隊列中的其它所有除我們使用代碼添加到主隊列的任務(wù)的任務(wù)都執(zhí)行完畢之后才會執(zhí)行我們使用代碼添加的任務(wù),。
主隊列同步任務(wù):容易阻塞主線程,所以不要這樣寫,。原因:我們自己代碼任務(wù)需要馬上執(zhí)行,,但是主線程正在執(zhí)行代碼任務(wù)的方法體,因此代碼任務(wù)就必須等待,,而主線程又在等待代碼任務(wù)的完成好去完成下面的任務(wù),,因此就形成了相互等待。整個主線程就被阻塞了,。
三,,全局隊列
全局隊列:本質(zhì)是一個并發(fā)隊列,由系統(tǒng)提供,,方便編程,,可以不用創(chuàng)建就直接使用。
獲取全局隊列的方法:dispatch_get_global_queue(long indentifier.unsigned long flags) /**
參數(shù)說明:
參數(shù)1:代表該任務(wù)的優(yōu)先級,,默認寫0就行,,不要使用系統(tǒng)提供的枚舉類型,,因為ios7和ios8的枚舉數(shù)值不一樣,,使用數(shù)字可以通用,。 參數(shù)2:蘋果保留關(guān)鍵字,一般也寫0
*/
全局隊列和并發(fā)隊列的區(qū)別:
1,全局隊列沒有名字,,但是并發(fā)隊列有名字,。有名字可以便于查看系統(tǒng)日志
2,,全局隊列是所有應(yīng)用程序共享的,。
3,在mrc的時候,,全局隊列不用手動釋放,,但是并發(fā)隊列需要,。
|
|