GCD是iOS多線程中最經常使用的一種。須要明確的幾點: 數據庫
任務:block 多線程
隊列:把任務放到隊列裏,隊列先進先出的原則。 併發
串行隊列:順序,一個一個執行。 異步
併發隊列:同時,同時執行不少個任務。 async
GCD中有倆個用來執行任務的函數。GCD裏面的函數都是以dispatch開頭的 函數
用同步的方式執行任務: dispatch_sync(對列, block);不會開啓新線程,在當前線程執行 spa
用異步的方式執行任務:dispatch_async(對列, block);確定會開新線程,在新線程中執行。 線程
隊列與同步異步的的組合方式共四類:分別看一下: code
若是是串行隊列,sync同步方法的話,通常只要使用「同步」執行,串行隊列添加的同步任務,會立馬執行,與不用GCD的順序是同樣的。 對象
若是是串行隊列,async異步執行的話,只會開一個新線程,並且全部任務都在這個新的線程裏面一個一個順序執行。
若是是併發隊列,sync同步執行的話,不開新線程,順序執行。與不用線程同樣。
若是是併發隊列,async異步執行的話,會開不少個線程,併發(不必定是一個一個的)執行。
總之若是是在同步的狀況下,那麼是不會開線程的,就是說同步的狀況下多線程就失去了意義,只有異步的狀況下才開線程。
同步和異步決定了要不要開啓新的線程
同步:在當前線程中執行任務,不具有開啓新線程的能力
異步:在新線程中執行任務,具有開啓新線程的能力。
併發和串行決定了任務的執行方式
併發:多個任務併發(同時)執行
串行:一個任務執行完畢後,再執行下一個任務
總結;開不開線程,由執行的方法決定,同步不開,異步確定開,開多少線程,由隊列決定,串行,最多開一個線程,併發,能夠開多個,具體開多少個,由GCD底層決定,程序控制不了。
主隊列;專門負責在主線程上調度任務,主隊列:特色,不容許開新線程,異步執行:會開新線程,在新線程執行,若是在主線程異步方法的話,不開新線程,沒有做用,至關於把任務放到主隊列,但不須要立刻執行,等主隊列空閒下來在執行。
若是在主隊列同步方法的話,不開新線程,把任務放到主隊列,但須要立刻執行,這會形成死鎖現象。
一。實現,用法
1.create方法建立隊列dispatch queue
1.1 建立一個串行隊列:參數:隊列標籤,隊列屬性
//屬性標籤DISPATCH_QUEUE_SERIAL or NULL dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);
1.2建立一個並行隊列:
dispatch_queue_t myConcurrrentDispatchQueue = dispatch_queue_create("com.example.gcd.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);
1.3異步實現
dispatch_async(myConcurrrentDispatchQueue, ^{ NSLog(@"block on myConcurrentDispatchQueue"); });
2.get方法建立隊列dispatch queue
2.1系統標準提供的dispatch_queue,主隊列,全局隊列的建立:
/* 系統標準提供的dispatch_queue,主隊列,全局隊列 */ dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue(); dispatch_queue_t globalDispatchQueueHign = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); dispatch_queue_t globalDiaptchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_queue_t globalDispatchQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
2.2調用
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ /* 可並行執行的處理 */ dispatch_async(dispatch_get_main_queue(), ^{ /* 在主線程中執行的處理 */ }); });
3
3.1 modify the priority of queue after which is created
dispatch_queue_t mySerialDispatchQueue1 = dispatch_queue_create("mySerialDispatchQueue1", NULL); dispatch_queue_t globalDispatchQueueBackgroud = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); dispatch_set_target_queue(mySerialDispatchQueue1, globalDispatchQueueBackgroud); //dispatch_queue_create函數生成的隊列無論是串行仍是並行的,隊列,都是用與默認優先級Global Dispatch Queue相同執行優先級的線程。而改變已有queue(隊列)的執行優先級要用dispatch_set_target_queue函數。第一個參數指數要變動的隊列來,第二個參數取其優先級給第一個,函數執行完後第一個參數的隊列的優先級和第二個參數的優先級相同,第二個參數不變。第一個參數若是制定系統提供的Main Dispatch Queue和Global Dispatch Queue則不知道會出現什麼情況,所以這些均不可指定。
3.2 在指定時間後把block追加到隊列中,而不是在指定時間後開始執行block,具體什麼時候開始執行由CPU調度決定。
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC); dispatch_after(time, dispatch_get_main_queue(), ^{ NSLog(@"waited at least three seconds"); });
3.3 Group(DISPATCH_QUEUE_CONCURRENT時,在追加到調度隊列中的多個處理所有結束後想執行結束處理使用)
dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue1, ^{ }); dispatch_group_async(group, queue1, ^{ }); dispatch_group_async(group, queue1, ^{ }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ //上面的queue1中的block所有執行完畢,就會執行這個方法中的block }); // dispatch_group_wait(<#dispatch_group_t group#>, <#dispatch_time_t timeout#>)
3.4 dispatch_barrier_async 數據庫訪問和文件訪問
dispatch_queue_t queue = dispatch_queue_create("xom.example.gcd.ForBarrier", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ }); dispatch_async(queue, ^{ }); // 上面的並行處理所有完成後纔會執行下面的, dispatch_barrier_async(queue, ^{ }); // s上面的dispatch_barrier_async裏的方法徹底執行完畢後纔會執行下面的方法,下面的方法又開始並行執行。 dispatch_async(queue, ^{ }); dispatch_async(queue, ^{ });
3.5 dispatch_walltime函數用於計算絕對時間,使用struct timespec 類型的時間獲得dispatch_time_t 類型的值。而struct timespec類型的時間能夠很輕鬆的經過NSDate類對象生成
//下面函數可由NSDate類對象獲取能傳遞給dispatch_after函數的dispatch_time_t類型的值。 dispatch_time_t getDispatchTimeByDate(NSDate *date) { NSTimeInterval interval; double second, subsecond; struct timespec time; dispatch_time_t millestone; interval = [date timeIntervalSince1970]; subsecond = modf(interval, &second); time.tv_sec = second; time.tv_nsec = subsecond *NSEC_PER_SEC; millestone = dispatch_walltime(&time, 0); return millestone; }