GCD - 實戰練習

實戰一: 使用串行隊列實現簡單的預加載

主要思路: 使用gcd在子線程中創建并初始化一個ViewController,在其加載完畢后,將其push入navigation controller中
簡要代碼如下:

@implementation DWClassA
{
    dispatch_queue_t _serialQueue;
    UINavigationController *_navController;
}
  
- (dispatch_queue_t)serialQueue
{
    if (!_serialQueue) {
        _serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);//創建串行隊列
    }
    return _serialQueue;
}
  
- (void)prepareViewController
{
    dispatch_async([self serialQueue], ^{//把block中的任務放入串行隊列中執行,這是第一個任務
        self.viewController = [[[DWViewController alloc] init] autorelease];
        sleep(2);//假裝這個viewController創建起來很花時間。。其實view都還沒加載,根本不花時間。
        NSLog(@"prepared");
    });
}
  
- (void)goToViewController
{
    dispatch_async([self serialQueue], ^{//第二個任務,推入viewController
        NSLog(@"go");
        dispatch_async(dispatch_get_main_queue(), ^{//涉及UI更新的操作,放入主線程中
            [_navController pushViewController:self.viewController animated:YES];
        });
    });
}
  
- (void)dealloc
{
    _serialQueue && dispatch_release(_serialQueue);
    [_navController release];
    [_viewController release];
    [super dealloc];
}
@end

首先我們創建了一個串行隊列(使用DISPATCH_QUEUE_SERIAL作為參數),我們知道,將多個任務dispatch至一個串行隊列,可以達到線程同步的效果,并且可以避免編寫Lock相關的代碼。我們使用一個方法來封裝這個串行隊列的創建,使得后續操作都能取得這個串行隊列

緊接著我們在prepare函數中,將創建并初始化ViewController的任務dispatch至串行隊列中,一旦dispatch,任務將立即開始執行,這里我使用sleep函數來模擬一個需要較長時間來初始化的viewcontroller,并且sleep了夸張的兩秒鐘。

然后我們在goTo函數中,將push任務dispatch至前述的串行隊列中,當初始化完成后,會自動接著執行push任務,當然,如果dispatch這個push任務時,如果前述的初始化任務早已完成,那么push任務將被立即執行。值得注意的是,在Cocoa開發中,我們必須將涉及UI更新的操作(即使這個操作不會被立即顯示在屏幕中)放在主線程中執行,這是Apple在文檔中規定的。

實際上Apple規定UIKit的方法都必須放在主線程中調用,事實證明,確實很多不涉及UI操作的UIKit方法都不能在子線程中調用,甚至一些文件加載的函數。而其根本原因是UIKit的這些方法都在內部調用了一些可能產生競態的資源(很多方法會調用render context來進行中間轉換等操作),而一些UIKit方法被驗證確實能放在子線程中調用(雖然不推薦這么做,因為這么做不穩定,你不能確定某一天Apple會修改這些方法的內部實現而導致其只能在主線程中執行)也印證了這一點。

最后我們在dealloc函數中釋放應該釋放的資源,注意dispatch_release方法不可以傳入一個NULL指針,這將導致崩潰。

在GCD的頭文件中我們會發現這句注釋:The result of passing NULL in this parameter is undefined.也就是說,不像free函數那樣(free函數由POSIX定義傳入NULL則什么都不干),dispatch_release是不能接受空指針的。

參考鏈接:http://www.cocoachina.com/ios/20161117/18112.html

實戰二:資源競爭

參考鏈接:http://mobile.51cto.com/hot-403011.htm
http://www.dreamingwish.com/article/gcd-practice-io-race.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容