只需知道如何開線程、會看相關的第三方框架便可。markdown
任務:執行什麼操做 隊列:用來存聽任務多線程
隊列類型:併發
(Concurrent Dispatch Queue)
可讓多個任務併發執行(自動開啓多個線程同時執行任務) 在異步dispatch_async
函數下才有效app
(Serial Dispatch Queue)
讓任務一個接着一個地執行(一個任務執行完畢後,再執行下一個) 按照FIFO順序執行。框架
任務派發:異步
指阻塞當前線程,既要等待添加的耗時任務塊Block完成後,函數才能返回,後面的代碼才能繼續執行。async
指將任務添加到隊列後,函數當即返回,後面的代碼不用等待添加的任務完成便可立刻執行。異步提交沒法肯定任務執行順序。函數
GCD多線程常常會使用 同步函數dispatch_sync
、異步函數dispatch_async
,向指定隊列 添加任務。url
各類隊列的執行效果spa
凡是放到主隊列中的任務,都必須在主線程中執行。
1.異步函數+主隊列
串行執行,全部任務都在主線程中執行,不會開線程
2.同步函數+主隊列————》會死鎖!通常不用。
主隊列的特色:若是主隊列發現當前主線程有任務在執行,那麼它會暫停隊列中的任務,直到主線程空閒爲止。
說明:在更新UI時回到了主線程(經過新設一個同步/異步函數,隊列參數爲主隊列)
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//...作一些任務
dispatch_sync(dispatch_get_main_queue(), ^{
//回到主線程,更新UI
});
});
複製代碼
舉例,開啓子線程下載圖片
//1.獲取一個 全局串行隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
__weak typeof(self) weakSelf = self;
//2.把任務添加到隊列中執行
dispatch_async(queue, ^{
NSURL *url = [NSURL URLWithString:_imgString];
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage * bgImage = [UIImage imageWithData:imageData];
bgImage = [bgImage applyLightEffectAtFrame:CGRectMake(0, 0, bgImage.size.width, bgImage.size.height)];
//3.回到主線程
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.backImageView.image = bgImage;
});
});
複製代碼
int64_t delayInSeconds = 10.0; // 延遲的時間
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// do something ... ...
});
或
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)( 10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// ...
});
複製代碼
這個應用程序只執行一次,再也不執行
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//...
});
複製代碼
不能應用於懶加載。應用於單例模式。
用於控制異步函數的執行順序,只有執行完柵欄函數,才能執行後面的隊列任務。使用時,必須本身建立隊列,不能使用全局併發隊列。
同步函數沒有必要用柵欄函數。
內部會開子線程和主線程一塊兒完成遍歷任務,異步執行任務
dispatch_async(dispatch_get_main_queue(), ^{
});
複製代碼
用於控制異步函數的執行順序。可避免數據競爭。使用時,必須本身建立隊列,不能使用全局併發隊列。
//建立隊列
dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_CONCURRENT);
//異步函數
dispatch_async(queue, ^{
//....異步任務1
});
dispatch_async(queue, ^{
//....異步任務2
});
//柵欄函數
dispatch_barrier_async(queue, ^{
//...
});
複製代碼
一個dispatch barrier
容許在一個併發隊列中建立一個同步點。當在併發隊列中遇到一個barrier
, 他會延遲執行barrier
的block,等待全部在barrier以前提交的blocks執行結束。 這時,barrier
block本身開始執行。 以後, 隊列繼續正常的執行操做。
某幾個隊列的任務都完成後,再執行其餘任務
//建立隊列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
/建立隊列組
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
//...異步任務1
});
dispatch_group_async(group, queue, ^{
//...異步任務2
});
dispatch_group_async(group, queue, ^{
//...異步任務3
});
// 攔截通知,當隊列組裏的任務都完成了,會進入下面這個方法
dispatch_group_notify(group, queue, ^{
//... ...
});
複製代碼
如,加載多個圖片
// 使用Dispatch Group追加block到Global Group Queue,這些block若是所有執行完畢,
就會執行Main Dispatch Queue中的結束處理的block。
// 建立隊列組
dispatch_group_t group = dispatch_group_create();
// 獲取全局併發隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, queue, ^{ /*加載圖片1 */ });
dispatch_group_async(group, queue, ^{ /*加載圖片2 */ });
dispatch_group_async(group, queue, ^{ /*加載圖片3 */ });
// 當併發隊列組中的任務執行完畢後纔會執行這裏的代碼
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 合併圖片
});
複製代碼
/* 在指定線程上定義計時器 */
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
/* 開始的時間 */
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
/* 設置計時器 ,時間間隔 5s */
dispatch_source_set_timer(_timer, when, 5.0 * NSEC_PER_SEC, 0);
/* 計時器回調block */
dispatch_source_set_event_handler(_timer, ^{
// do something
NSLog(@"須要作的任務!");
});
/* 開啓計時器 */
dispatch_resume(_timer);
self.timer = _timer; // 強引用計時器對象(必須)
複製代碼
必須銷燬self.timer才能終止定時任務:
self.timer = nil ;
能夠取消還未執行的線程。可是沒辦法作到取消一個正在執行的線程。
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_block_t block1 = dispatch_block_create(0, ^{
NSLog(@"block1");
});
dispatch_block_t block2 = dispatch_block_create(0, ^{
NSLog(@"block2");
});
dispatch_block_t block3 = dispatch_block_create(0, ^{
NSLog(@"block3");
});
dispatch_async(queue, block1);
dispatch_async(queue, block2);
dispatch_async(queue, block3);
dispatch_block_cancel(block3); // 取消 block3
複製代碼
投機取巧:使用臨時變量 + return 方式取消 正在執行的Block。
__block BOOL gcdFlag = NO; // 臨時變量
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (long i=0; i<1000; i++) {
NSLog(@"正在執行第i次:%ld",i);
sleep(0.1);
if (gcdFlag==YES) { // 判斷並終止
NSLog(@"終止");
return ;
}
};
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"我要中止啦");
gcdFlag = YES;
});
複製代碼