自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

GCD介紹(四):完結(jié)

移動開發(fā) iOS
本文為大家介紹了dispatch queue的掛起、恢復(fù)和目標重定,以及這些功能的一些用途。另外,我們還介紹了如何使用dispatch 信號量和單次初始化功能。到此,我已經(jīng)完成了GCD如何運作以及如何使用的介紹。

[[77417]]

Dispatch Queue掛起

dispatch queue可以被掛起和恢復(fù)。使用 dispatch_suspend函數(shù)來掛起,使用  dispatch_resume 函數(shù)來恢復(fù)。這兩個函數(shù)的行為是如你所愿的。另外,這兩個函數(shù)也可以用于dispatch source。

一個要注意的地方是,dispatch queue的掛起是block粒度的。換句話說,掛起一個queue并不會將當前正在執(zhí)行的block掛起。它會允許當前執(zhí)行的block執(zhí)行完畢,然后后續(xù)的block不再會被執(zhí)行,直至queue被恢復(fù)。

還有一個注意點:從man頁上得來的:如果你掛起了一個queue或者source,那么銷毀它之前,必須先對其進行恢復(fù)。

Dispatch Queue目標指定

所有的用戶隊列都有一個目標隊列概念。從本質(zhì)上講,一個用戶隊列實際上是不執(zhí)行任何任務(wù)的,但是它會將任務(wù)傳遞給它的目標隊列來執(zhí)行。通常,目標隊列是默認優(yōu)先級的全局隊列。

用戶隊列的目標隊列可以用函數(shù) dispatch_set_target_queue來修改。我們可以將任意dispatch queue傳遞給這個函數(shù),甚至可以是另一個用戶隊列,只要別構(gòu)成循環(huán)就行。這個函數(shù)可以用來設(shè)定用戶隊列的優(yōu)先級。比如我們可以將用戶隊列的目標隊列設(shè)定為低優(yōu)先級的全局隊列,那么我們的用戶隊列中的任務(wù)都會以低優(yōu)先級執(zhí)行。高優(yōu)先級也是一樣道理。

有一個用途,是將用戶隊列的目標定為main queue。這會導致所有提交到該用戶隊列的block在主線程中執(zhí)行。這樣做來替代直接在主線程中執(zhí)行代碼的好處在于,我們的用戶隊列可以單獨地被掛起和恢復(fù),還可以被重定目標至一個全局隊列,然后所有的block會變成在全局隊列上執(zhí)行(只要你確保你的代碼離開主線程不會有問題)。

還有一個用途,是將一個用戶隊列的目標隊列指定為另一個用戶隊列。這樣做可以強制多個隊列相互協(xié)調(diào)地串行執(zhí)行,這樣足以構(gòu)建一組隊列,通過掛起和暫停那個目標隊列,我們可以掛起和暫停整個組。想象這樣一個程序:它掃描一組目錄并且加載目錄中的內(nèi)容。為了避免磁盤競爭,我們要確定在同一個物理磁盤上同時只有一個文件加載任務(wù)在執(zhí)行。而希望可以同時從不同的物理磁盤上讀取多個文件。要實現(xiàn)這個,我們要做的就是創(chuàng)建一個dispatch queue結(jié)構(gòu),該結(jié)構(gòu)為磁盤結(jié)構(gòu)的鏡像。

首先,我們會掃描系統(tǒng)并找到各個磁盤,為每個磁盤創(chuàng)建一個用戶隊列。然后掃描文件系統(tǒng),并為每個文件系統(tǒng)創(chuàng)建一個用戶隊列,將這些用戶隊列的目標隊列指向合適的磁盤用戶隊列。最后,每個目錄掃描器有自己的隊列,其目標隊列指向目錄所在的文件系統(tǒng)的隊列。目錄掃描器枚舉自己的目錄并為每個文件向自己的隊列提交一個block。由于整個系統(tǒng)的建立方式,就使得每個物理磁盤被串行訪問,而多個物理磁盤被并行訪問。除了隊列初始化過程,我們根本不需要手動干預(yù)什么東西。

信號量

dispatch的信號量是像其他的信號量一樣的,如果你熟悉其他多線程系統(tǒng)中的信號量,那么這一節(jié)的東西再好理解不過了。

信號量是一個整形值并且具有一個初始計數(shù)值,并且支持兩個操作:信號通知和等待。當一個信號量被信號通知,其計數(shù)會被增加。當一個線程在一個信號量上等待時,線程會被阻塞(如果有必要的話),直至計數(shù)器大于零,然后線程會減少這個計數(shù)。

我們使用函數(shù)  dispatch_semaphore_create 來創(chuàng)建dispatch信號量,使用函數(shù)  dispatch_semaphore_signal 來信號通知,使用函數(shù) dispatch_semaphore_wait 來等待。這些函數(shù)的man頁有兩個很好的例子,展示了怎樣使用信號量來同步任務(wù)和有限資源訪問控制。

單次初始化

GCD還提供單詞初始化支持,這個與pthread中的函數(shù)  pthread_once 很相似。GCD提供的方式的優(yōu)點在于它使用block而非函數(shù)指針,這就允許更自然的代碼方式:

這個特性的主要用途是惰性單例初始化或者其他的線程安全數(shù)據(jù)共享。典型的單例初始化技術(shù)看起來像這樣(線程安全的):

  1. + (id)sharedWhatever 
  2.     static Whatever *whatever = nil; 
  3.     @synchronized([Whatever class]) 
  4.     { 
  5.         if(!whatever) 
  6.             whatever = [[Whatever alloc] init]; 
  7.     } 
  8.     return whatever; 

這挺好的,但是代價比較昂貴;每次調(diào)用  +sharedWhatever 函數(shù)都會付出取鎖的代價,即使這個鎖只需要進行一次。確實有更風騷的方式來實現(xiàn)這個,使用類似雙向鎖或者是原子操作的東西,但是這樣挺難弄而且容易出錯。

使用GCD,我們可以這樣重寫上面的方法,使用函數(shù) dispatch_once

  1. + (id)sharedWhatever 
  2.     static dispatch_once_t pred; 
  3.     static Whatever *whatever = nil; 
  4.     dispatch_once(&pred, ^{ 
  5.         whatever = [[Whatever alloc] init]; 
  6.     }); 
  7.     return whatever; 

這個稍微比 @synchronized方法簡單些,并且GCD確保以更快的方式完成這些檢測,它保證block中的代碼在任何線程通過  dispatch_once 調(diào)用之前被執(zhí)行,但它不會強制每次調(diào)用這個函數(shù)都讓代碼進行同步控制。實際上,如果你去看這個函數(shù)所在的頭文件,你會發(fā)現(xiàn)目前它的實現(xiàn)其實是一個宏,進行了內(nèi)聯(lián)的初始化測試,這意味著通常情況下,你不用付出函數(shù)調(diào)用的負載代價,并且會有更少的同步控制負載。

結(jié)論

這一章,我們介紹了dispatch queue的掛起、恢復(fù)和目標重定,以及這些功能的一些用途。另外,我們還介紹了如何使用dispatch 信號量和單次初始化功能。到此,我已經(jīng)完成了GCD如何運作以及如何使用的介紹。

責任編輯:閆佳明 來源: dreamingwish
相關(guān)推薦

2013-07-15 16:18:08

2013-07-15 16:00:59

2013-07-15 15:51:32

iOS多線程GCD基本概念Dispatch Qu

2013-07-15 15:23:03

iOS多線程GCD

2019-05-07 15:38:48

手機CPU大小核

2010-03-04 13:54:39

Linux壓縮命令

2023-02-21 16:46:04

loongarch架構(gòu)

2013-07-15 16:55:54

iOS多線程GCD實戰(zhàn)資源競爭

2010-03-05 11:58:52

2011-06-24 10:53:14

四處一詞SEO

2016-11-15 15:50:22

linux基礎(chǔ)命令vim

2010-06-12 18:12:34

UML類圖關(guān)系

2011-07-22 09:43:37

java

2013-05-13 09:48:47

網(wǎng)絡(luò)接入接入方法綜合布線

2013-07-19 14:35:59

iOS中BlockiOS開發(fā)學習

2021-04-27 19:20:54

微應(yīng)用模塊聯(lián)邦

2024-08-27 08:29:49

2011-06-22 08:38:35

Java EE

2010-03-03 13:50:40

Python文件

2020-04-22 10:02:48

編程高德納算法
點贊
收藏

51CTO技術(shù)棧公眾號