GCD通過任務和隊列實現多線程功能
同步
同步執行任務的函數
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block),Block類型
void dispatch_sync_f(dispatch_queue_t queue, void *context, dispatch_function_t work),函數類型(每個Block類型都對應一個函數類型)
同步執行任務的其他函數(barrier),在前面的任務執行完畢它才執行,它后邊的任務等它執行完畢才執行
void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block),block類型
dispatch_barrier_sync_f(dispatch_queue_t queue, void *context, dispatch_function_t work),函數類型
異步
異步執行任務的函數(參數意義與同步函數相同)
異步執行任務的其他函數(barrier),在前面的任務執行完畢它才執行,它后邊的任務等它執行完畢才執行(參數意義與同步函數相同)
并發隊列
串行隊列
隊列的種類
串行隊列
dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr)
并發隊列
dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr)
主隊列(串行,只能在主線程中運行)
全局隊列(并發)
同步函數
同步函數主隊列
/**- 運行在主線程主隊列(未開啟新的線程),主線程被卡死- 原因:任務代碼等待著當前函數執行完畢才能執行(當前函數正在執行且未執行完畢); 當前函數等待著任務代碼 執行完畢才能執行(當前任務正在執行且未執行完畢); 相互等待,出現死鎖*///獲取主隊列dispatch_queue_t queue = dispatch_get_main_queue();//添加任務到隊列dispatch_sync(queue, ^{ //任務1代碼});dispatch_sync(queue, ^{ //任務2代碼});
同步函數串行隊列
/**- 運行在主線程串行非主隊列(未開啟新的線程),任務串行執行*///創建串行隊列dispatch_queue_t queue = dispatch_queue_create("com.23565@QQ", DISPATCH_QUEUE_SERIAL);//添加任務到隊列dispatch_sync(queue, ^{ //任務1代碼});dispatch_sync(queue, ^{ //任務2代碼});
同步函數并發隊列
/**- 運行在非主線程并發隊列(未開啟新的線程),任務串行執行*///獲取全局隊列(并發)dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//將任務加至隊列dispatch_sync(queue, ^{ //任務1代碼});dispatch_sync(queue, ^{ //任務2代碼});
異步函數
異步函數主隊列
/**- 運行在主線程主隊列(未開啟新的線程),任務串行執行*/// 獲得主隊列dispatch_queue_t queue = dispatch_get_main_queue();// 將任務加入隊列dispatch_async(queue, ^{ //任務1代碼});dispatch_async(queue, ^{ //任務2代碼});
異步函數串行隊列
/**- 運行在主函數串行非主隊列(未開啟新的線程),任務串行執行*///創建串行隊列dispatch_queue_t queue = dispatch_queue_create("com.23565@qq", DISPATCH_QUEUE_SERIAL);//將任務加至隊列dispatch_async(queue, ^{ //任務1代碼})dispatch_async(queue, ^{ //任務2代碼})
異步函數并發隊列
/**- 運行在非主線程并發隊列(開啟新的線程),任務并發執行- 系統根據任務創建線程(無法確定任務執行在哪個線程)*///獲得全局并發隊列dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//將任務加入隊列dispatch_async(queue, ^{ //任務1代碼});dispatch_async(queue, ^{ //任務2代碼});
從主線程到子線程
注意
實現代碼
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //需要在子線程中執行的任務代碼 })
從子線程到主線程
注意
實現代碼
dispatch_async(dispatch_get_main_queue(), ^{ //需要在主線程中執行的代碼 })
單次執行(通常用在單例模式的設計中)
//定義一個標記static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{ //此處的代碼只會被執行一次});
延遲執行
/**- 方法一(GCD)*/dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //此處的代碼將延遲執行});/**- 方法二(performSelector)*/[self performSelector:@selector(run) withObject:self afterDelay:2.0];/**- 方法三(NSTimer)*/[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO]
快速迭代
void dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t))/** iterations:迭代執行的次數 queue:任務隊列 block:迭代執行的代碼 size_t:用來定義當前迭代到第幾次,需要自己添加,如在size_t后添加index索引,記錄當前的迭代次數*/
Barrier
/**- Barrier中的任務,只能在它前面的任務執行完畢才能執行 Barrier后的任務,只能等到它執行完畢才能執行- 要將隊列添加到自己創建的并發隊列中,否其功能等同于函數 void dispatch_async(dispatch_queue_t queue, dispatch_block_t block)*///創建隊列(通常是自己創建的并發隊列)dispatch_queue_t queue = dispatch_queue_create("123", DISPATCH_QUEUE_CONCURRENT);//將任務添加到隊列dispatch_async(queue, ^{ //在Barrier前執行的任務代碼});dispatch_barrier_async(queue, ^{ //Barrier中的任務代碼});dispatch_async(queue, ^{ //在Barrier后執行的任務代碼});
隊列組
//獲取全局并發隊列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, ^{ //任務1代碼 });dispatch_group_async(group, queue, ^{ //任務2代碼 });dispatch_group_notify(group, queue, ^{ //任務3代碼 /** group組中的所有任務執行完畢在執行 若group為空,則立即執行 */});
實現原理
實現代碼
//獲得隊列dispatch_queue_t queue = dispatch_get_main_queue();//創建一個定時器self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);//設置定時器的各種屬性(起止時間)dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(8.0 * NSEC_PER_SEC));uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);//設置dispatch_source_set_timer(self.timer, start, interval, 0);//設置回調dispatch_source_set_event_handler(self.timer, ^{ //定時器被觸發時所要執行的代碼});//開啟定時器dispatch_resume(self.timer);//取消定時器dispatch_cancel(self.timer);
新聞熱點
疑難解答