GCD——Grand Central Dispatch 是基於C語言的框架,能夠充分利用多核,也是蘋果官方推薦使用的多線程技術。程序員
GCD是蘋果公司爲多核的並行運算提出的解決方案編程
GCD會自動利用更多的CPU內核(好比雙核、四核)多線程
GCD會自動管理線程的生命週期(建立線程、調度任務、銷燬線程)併發
1 #import "ViewController.h" 2 3 @interface ViewController () 4 5 @end 6 7 @implementation ViewController 8 9 /* 10 //寫以前,再來溫習溫習。 11 GCD的使用: 12 一 :隊列 13 1.串行隊列:添加到隊列中的任務是一個一個執行的 14 2.併發(行)隊列:添加到隊列中的任務是多個同時執行的 15 3.主隊列:裏面的任務都是在主線程執行的。 16 4.全局隊列:並行(發)隊列 17 18 二:同步、異步 19 一、同步:須要後面的任務等待,不會開啓新的線程,會直接使用當前的線程 20 21 二、異步:不須要後面的任務等待,會開啓新的線程 22 */ 23 24 - (void)viewDidLoad { 25 [super viewDidLoad]; 26 27 /*---------建立併發隊列---------*/ 28 29 //1.建立並行隊列 30 dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT); 31 32 //2.獲取全局隊列(並行隊列) 33 /*優先級<#long identifier#> 34 DISPATCH_QUEUE_PRIORITY_HIGH 35 DISPATCH_QUEUE_PRIORITY_DEFAULT 36 DISPATCH_QUEUE_PRIORITY_LOW 37 DISPATCH_QUEUE_PRIORITY_BACKGROUND 38 */ 39 40 dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 41 42 //(1)在併發隊列添加異步任務 43 44 dispatch_async(queue2, ^{ 45 46 for (int i = 0; i < 50 ;i ++) { 47 48 NSLog(@"1---------1"); 49 } 50 51 52 }); 53 54 dispatch_async(queue2, ^{ 55 56 57 for (int i = 0; i < 50 ;i ++) { 58 59 NSLog(@"2---------2"); 60 } 61 62 63 });
打印結果:框架
1 dispatch_sync(queue2, ^{ 2 3 @autoreleasepool { 4 for (int i = 0; i < 50 ;i ++) { 5 6 NSLog(@"1---------1"); 7 } 8 } 9 }); 10 11 12 dispatch_sync(queue2, ^{ 13 14 @autoreleasepool { 15 for (int i = 0; i < 50 ;i ++) { 16 17 NSLog(@"2---------2"); 18 } 19 } 20 });
這個打印結果相信不用說,咱們都知道確定是先執行1 在執行2異步
1 /*---------建立串行----------*/ 2 3 dispatch_queue_t queue = dispatch_queue_create("queue3", DISPATCH_QUEUE_SERIAL); 4 5 //向串行隊列異步添加任務 6 dispatch_async(queue, ^{ 7 8 for (int i=0; i<50; i++) { 9 NSLog(@"🐷....i:%d",i); 10 } 11 12 }); 13 14 dispatch_async(queue, ^{ 15 16 for (int i=0; i<50; i++) { 17 NSLog(@"🐶....i:%d",i); 18 } 19 20 });
打印結果:async
儘管是異步添加任務,可是該隊列是串行隊列,因此豬 先被執行,而後才執行狗。ide
若是此時咱們再在viewDidLoad中也就是在狗的for訓話下面添加一個for循環的話你能想象出結果嗎?spa
1 for (int i=0; i<100; i++) { 2 NSLog(@"🐱....i:%d",i); 3 }
打印結果:線程
向串行隊列同步添加任務
dispatch_sync(queue, ^{ for (int i=0; i<50; i++) { NSLog(@"🐶....i:%d",i); } }); dispatch_sync(queue, ^{ for (int i=0; i<100; i++) { NSLog(@"🐱....i:%d",i); } }); for (int i=0; i<100; i++) { NSLog(@"🐷....i:%d",i); }
運行結果毫無疑問。狗-----》貓----------》豬;時刻記着同步添加任務,不會開啓新的線程,會直接使用當前線程。那麼確定這三個任務也是在當前的主線程。
介紹完這些,還有一個重要的東西那就是死鎖
讓咱們來看一下
獲取主隊列:
dispatch_queue_t mainQueue = dispatch_get_main_queue();
分配任務:
1 NSLog(@"任務開始啦!!!"); 2 //同步添加任務 3 dispatch_sync(mainQueue, ^{ 4 5 NSLog(@"任務添加"); 6 7 }); 8 9 NSLog(@"結束");
毫無疑問第一個打印確定是 第一行的「任務開始啦!!!」,那麼接下來走第三行代碼,由於是Block因此第五行的代碼要在第九行的打印執行結束後才能被執行(block回調),又由於是同步添加任務,因此第九行代碼要在上面的任務執行完才能開始。因此編譯器猶豫不知道該執行那一個。會形成死鎖。
打印結果:
總結:(1)在使用主隊列時,絕對不能夠在主隊列中同步添加任務,會形成死鎖。
(2)併發隊列:同步添加不會開啓新的線程,異步添加會開啓多條線程。
(3)串行隊列:同步添加不會開啓新的線程,異步添加會開啓一條線程。
(4)由(2)和(3)得出結論同步添加任務,不具有開啓線程的能力。異步添加任務開啓線程的條數由當前隊列決定,串行隊列開啓一條線程,並行隊列開啓多條。