iOS學習篇章5--GCD

GCD


1、定義:

Grand Central Dispatch;

iOS的一種底層多線程機制;

多核編程的解決方法;

使用內聯的形式,將block代碼,放置其中;

GCD可以說是依賴於Block,瞭解:Block

2、控制:

dispatch_async(queue, block);

其中 queue 隊列,系統提供兩種,一種是串行隊列(SerialDispatchQueue),一種是並行隊列(ConcurrentDispatchQueue);

block 是其中的代碼塊,queue 隊列控制block的使用形式;


3、MainDispatchQueue:

將任務插入主線程的RunLoop當中去執行,是個串行隊列;

可以使用它來更新UI;

獲取主線程隊列:

dispatch_queue_t  queue = dispatch_get_main_queue(); 

簡略的執行:

// 主線程執行: 
dispatch_async(dispatch_get_main_queue(), ^{ 
  // something 
});


4、GlobalDispatchQueue:


是一個全局的並行隊列,有高、默認、低和後臺4個優先級;

可以併發地執行多個任務;

DISPATCH_QUEUE_PRIORITY_HIGHT、

DISPATCH_QUEUE_PRIORITY_DEFAULT、

DISPATCH_QUEUE_PRIORITY_LOW、

DISPATCH_QUEUE_PRIORITY_BACKGROUND、

獲取全局隊列:

dispatch queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0)

簡略的執行:(並行三個任務隊列)

//  後臺執行:
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0), ^{
      // something
 });
//  後臺執行:
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0), ^{
      // something
 });
//  後臺執行:
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0), ^{
      // something
 });




5、SerialDispatchQueue:

串行隊列;

用於按順序同步訪問,可創建任意數量的串行隊列,各個串行隊列之間是併發的。

線程池只提供一個線程用來執行任務,所以後一個任務必須等到前一個任務執行結束才能開始。

創建串行隊列:

dispatch_queue_t myQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL);  


執行:

	//串行隊列
    dispatch_async(dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL), ^{  
	// do something
    }); 
    dispatch_async(dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL), ^{  
	// do something
    }); 


dispatch_async 可以去執行多個來驗證是否是串行的;

6、普遍用法:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
        // 做一些耗時操作
        dispatch_async(dispatch_get_main_queue(), ^{  
            // update UI  
        });  
    }); 

7、執行一次的隊列:

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
	_shareInstance = [[self alloc] init];
});
可以保證整個應用程序生命週期中某段代碼只被執行一次!

適用於:單利模式


8、延遲執行:

// 延遲2秒執行:
 double delayInSeconds = 2.0;
 dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
 dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
     // code to be executed on the main queue after delay

 });


9、多次執行:

執行某個代碼片段N次。

int n=5;
dispatch_apply(n, globalQ, ^(size_t index) {

// 執行5次

});
其中的隊列,

可以是串行,也可以是並行隊列;



10、組任務:

dispatch_group_async可以實現監聽一組任務是否完成,完成後得到通知執行其他的操作;

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
    dispatch_group_t group = dispatch_group_create();  
    dispatch_group_async(group, queue, ^{  

    });  
    dispatch_group_async(group, queue, ^{  

    });  
    dispatch_group_async(group, queue, ^{  

    });  
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{  
        NSLog(@"main thread.");  
    });  

並行三個任務處於一個組中,組中任務執行完成後通知;


11、併發安全性:

在併發執行時的數據讀取和寫入,需要考慮數據的安全性;

由於dispatch_get_global_queue 無法控制其中的隊列,那麼如何做呢?

dispatch_barrier_async 

在前面的隊列執行完成之後,纔會繼續下面的隊列;


dispatch_queue_t queue = dispatch_queue_create("com.qb.queue.GCD", DISPATCH_QUEUE_CONCURRENT);  
      
    dispatch_async(queue, ^{  
    });  
    dispatch_async(queue, ^{  
    });  
    dispatch_barrier_async(queue, ^{  
        NSLog(@"dispatch_barrier_async");  
          
    });  
    dispatch_async(queue, ^{  
    });  


第一個和第二並行隊列執行完成之後,纔會執行dispatch_barrier_async,然後才繼續執行後續的隊列;



12、優先級:

通過dispatch_set_target_queue函數可以設置一個dispatch queue的優先級;

或者指定一個dispatch source相應的事件處理提交到哪個queue上。


dispatch_queue_t currentQueue = dispatch_queue_create("com.qb.demo.GCD", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t targetQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(currentQueue, targetQueue);

13、最後:

在沒有使用GCD時,當app被按home鍵退出後,app僅有最多5秒鐘的時候做一些保存或清理資源的工作。
在使用GCD後,app最多有10分鐘的時間在後臺長久運行。
這個時間可以用來做清理本地緩存,發送統計數據等工作。

即:GCD的另一個用處是可以讓程序在後臺較長久的運行。
(摘自網上,待驗證)


- (void)applicationDidEnterBackground:(UIApplication *)application { 
        [self beingBackgroundUpdateTask]; 
    
} 

- (void)beingBackgroundUpdateTask { 
  self.backgroundUpdateTask = [[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:^{ 
             [self endBackgroundUpdateTask];
  }]; 
} 

- (void)endBackgroundUpdateTask {
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章