iOS多線程開發之深刻GCD

iOS多線程開發之深刻GCD

1、前言

        在之前的一些系列博客中,對iOS中線程的管理作了總結,其中涵蓋了GCD的相關基礎知識:http://my.oschina.net/u/2340880/blog/417746。那裏面將GCD的線程管理能力,列隊組能力,經過信號和消息控制程序流程的能力都有介紹,這裏,咱們繼續深刻GCD的功能,經過GCD來處理一些邏輯更加複雜的代碼功能。編程

2、延時追加任務

        當咱們在程序中處理延時任務的時候,咱們通常會經過兩種方式,一種是經過定時器進行延時執行,另一種是經過以下的函數:安全

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

然而,若是咱們須要在多線程中進行延時操做,上面兩種方式會顯得十分麻煩,而且徒增代碼的複雜度。GCD爲咱們提供了一種方式:多線程

void  dispatch_after(dispatch_time_t when, dispatch_queue_t queue,  dispatch_block_t block);異步

這個方法有三個參數,第一個參數延時的時間,第二個參數爲將任務加入的隊列,第三個block爲要執行的任務。示例以下:async

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"1233");
    });

這裏經過dispatch_time來建立時間對象,將打印信息的方法在3S後加入主線程隊列。須要注意的是,這裏只是將任務延時加入隊列,並非執行,若是是加入同步隊列中,則會進入等待狀態。函數

 

3、數據存取的線程安全問題

 

        在進行多線程編程時,或許總會遇到一類問題,數據的競爭與線程的安全。這些問題若是咱們經過程序手動來控制難度將會很是大。GCD一樣爲咱們簡單的解決了這樣的問題。spa

首先,若是隻是在讀取數據,而不對數據作任何修改時,咱們並不須要處理安全問題,可讓多個任務同時進行讀取,但是若是要對數據進行寫的操做,那麼在同一時間,咱們就必須只能有一個任務在寫,GCD中有一個方法幫咱們完美的解決了這個問題,代碼以下:.net

//建立一個隊列
dispatch_queue_t queue = dispatch_queue_create("oneQueue", DISPATCH_QUEUE_CONCURRENT);
    //幾個任務同時讀操做
    dispatch_async(queue, ^{
        for (int i=0; i<5; i++) {
            NSLog(@"read1:%d",i);
        }
    });
    dispatch_async(queue, ^{
        for (int i=0; i<5; i++) {
            NSLog(@"read2:%d",i);
        }
    });
    //此處進行寫操做
    /*
    下面這個函數在加入隊列時不會執行,會等待已經開始的異步執行所有完成後再執行,而且在執行時,會阻塞其餘任務
    執行完成後,其餘任務從新進入異步執行
    */    
    dispatch_barrier_async(queue, ^{
        for (int i=0; i<5; i++) {
            NSLog(@"write:%d",i);
        }
    });
    //繼續進行異步讀操做
    dispatch_async(queue, ^{
        for (int i=0; i<5; i++) {
            NSLog(@"read3:%d",i);
        }
    });
    dispatch_async(queue, ^{
        for (int i=0; i<5; i++) {
            NSLog(@"read4:%d",i);
        }
    });
    dispatch_async(queue, ^{
        for (int i=0; i<5; i++) {
            NSLog(@"read5:%d",i);
        }
    });

打印信息以下:線程

能夠看出,讀操做是異步進行的,寫操做是等待後阻塞任務隊列獨立進行,結束後隊列恢復異步執行讀操做,這正是咱們須要的效果。code

 

4、GCD模式的單例

        一般狀況下,咱們的單例會是以下的樣子:

+(instancetype)shared{
    static Auto * obj;
    if (obj==nil) {
        obj = [[Auto alloc]init];
    }
    return obj;
}

這種經過讀取靜態變量的方式在大多數狀況下是沒問題的,但是並不能保證程序百分百的安全,由於在多線程的操做中,會有可能初始化多個對象,在GCD中,咱們可使用以下方式:

+(instancetype)shared{
    static Auto * obj;
    //dispatch_once_t對象能夠只保證執行一次
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        obj = [[Auto alloc]init];
    });
     return obj;
    
}

專一技術,熱愛生活,交流技術,也作朋友。

——琿少 QQ羣:203317592

相關文章
相關標籤/搜索