1.向並行隊列提交同步任務,(根據顯示結果可知:全部任務所有在主線程執行,全部任務都是按順序執行的)html
//線程與線程之間的執行速度多是不肯定的 //1. 建立一個並行隊列 dispatch_queue_t concurrentQueue = dispatch_queue_create("com.concurrentQueue", DISPATCH_QUEUE_CONCURRENT); //並行隊列中提交多個異步任務,任務的順序不能肯定 //同步提交任務任務的順序能夠肯定 dispatch_sync(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務一:%d", i); } }); NSLog(@"---1---"); dispatch_sync(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務二:%d", i); } }); NSLog(@"---2---"); dispatch_sync(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務三:%d", i); } }); NSLog(@"---3---");
2.向並行隊列提交異步任務(根據結果:全部任務都是在非主線程中執行的,並且任務執行的順序是不肯定的)編程
//並行隊列中提交多個異步任務,任務的順序不能肯定 dispatch_async(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務一:%d", i); } }); NSLog(@"---1---"); dispatch_async(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務二:%d", i); } }); NSLog(@"---2---"); dispatch_async(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務三:%d", i); } }); NSLog(@"---3---");
1.向串行隊列同步提交任務(從結果可知:全部任務都在主線程中執行,全部任務都是按順序執行的)數據結構
//1. 建立串行隊列,一個串行隊列對應一個線程 //1.1. 第一個參數是隊列的名稱 //1.2. 第二個參數是隊列的類型,NULL表示串行隊列 dispatch_queue_t serialQueue = dispatch_queue_create("com.serialQueue", DISPATCH_QUEUE_SERIAL); //2. 若是任務在不一樣的線程中執行,那麼它們的執行順序是不肯定的 dispatch_sync(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務一:%d", i); } }); NSLog(@"---1---"); dispatch_sync(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務二:%d", i); } }); NSLog(@"---2---"); dispatch_sync(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務三:%d", i); } }); NSLog(@"---3---");
2.向串行隊列提交異步任務(從結果可知:全部的任務都是在非主線程中執行的,全部的任務都是按順序執行的)併發
dispatch_async(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務一:%d", i); } }); NSLog(@"---1---"); dispatch_async(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務二:%d", i); } }); NSLog(@"---2---"); dispatch_async(serialQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } for (int i = 0; i < 100; i++) { NSLog(@"任務三:%d", i); } }); NSLog(@"---3---");
結果對比:異步
1.不論是串行隊列仍是並行隊列,同步提交任務都是在主線程中執行的,異步提交任務都是在非主線程中執行的(這裏相對於3.4來說的)async
2.並行隊列的任務,若是不在同一線程,能夠與主線程同時執行,主線程中的任務優先其餘線程的任務執行,但不排除其餘線程的任務和主線程的任務同時間進行函數
3.同步提交任務,任務所在的線程與提交任務所在的線程是同樣的優化
4.異步提交任務,任務所在的線程與提交任務所在的線程是不同的spa
5.同一線程,全部任務都是先進先出按順序來的(串行同步,並行同步都在主線程)線程
6.串行異步,任務在同一個線程,任務所在的線程與提交任務所在的線程是不同的(因此出現任務一和主線程的任務先執行,任務二和任務三後執行,由於任務一二三在同一個線程)
7.並行異步,任務在不一樣線程,任務所在的線程與提交任務所在的線程是不同的(因此出現任務和主線程的任務都是同時執行)
因此根據上面的總結能夠體會到,任務的執行順序和會不會阻塞,我門只須要判斷清楚任務所在的線程就能夠了,不一樣線程能夠同時執行,同一線程只能按順序執行
最後只需記住多個任務同時執行用: 並行異步 兩個任務同時執行用:串行異步 全部任務按前後順序執行 :串行同步,並行同步 可是這裏只是相對於一個線程編程的時候,好比主線程,若是在主線程裏面建立一個其餘的線程,而後同步提交任務,咱們是否是也能夠實現兩個甚至是多個任務同時運行了,這個還有待驗證
概念這裏參考 http://www.mamicode.com/info-detail-1010323.html 爲了避免麻煩就直接複製粘貼了
首先明確一下「同步&異步」「串行&併發」這兩組基本概念:
同步執行:好比這裏的dispatch_sync,這個函數會把一個block加入到指定的隊列中,並且會一直等到執行完blcok,這個函數才返回。所以在block執行完以前,調用dispatch_sync方法的線程是阻塞的。
與之對應的就有「異步執行」的概念:
異步執行:通常使用dispatch_async,這個函數也會把一個block加入到指定的隊列中,可是和同步執行不一樣的是,這個函數把block加入隊列後不等block的執行就馬上返回了。
接下來看一看另外一組相對的概念:「串行&併發」
串行隊列:好比這裏的dispatch_get_main_queue。這個隊列中全部任務,必定按照先來後到的順序執行。不只如此,還能夠保 證在執行某個任務時,在它前面進入隊列的全部任務確定執行完了。對於每個不一樣的串行隊列,系統會爲這個隊列創建惟一的線程來執行代碼。
與之相對的是併發隊列:
併發隊列:好比使用dispatch_get_global_queue。這個隊列中的任務也是按照先來後到的順序開始執行,注意是開始,可是它們的執行結束時間是不肯定的,取決於每一個任務的耗時。對於n個併發隊列,GCD不會建立對應的n個線程而是進行適當的優化
總結一下,到底什麼是死鎖。首先,雖然剛剛咱們提到了隊列和線程,以及它們之間的對應關係,可是死鎖必定是針對線程 而言的,隊列只是GCD給出的抽象數據結構。所謂的死鎖,必定是發生在一個或多個線程之間的。那麼死鎖和線程阻塞的關係呢,能夠這麼理解,雙向的阻塞致使 了死鎖。由於阻塞是線程中常常發生的事情,最多就是主線程的阻塞影響了用戶體驗。而一旦出現了雙向的阻塞,就致使了死鎖。咱們能夠看到,主線程是串行的, 在執行某一個任務的時候線程被阻塞了,而這個任務(dispatch_sync)在執行時,又要求阻塞主線程,從而致使了互相的阻塞,也就是死鎖
分析:若是阻塞時間過長久會造成「界面假死」,若是雙向阻塞就會造成死鎖,這兩種狀況的造成咱們就不考慮異步提交了,由於異步提交是根本不會造成阻塞,因此咱們只看同步提交的狀況
//1. 主隊列裏的任務必定在主線程上執行 //2. 不該該在主線程中執行耗時的任務,不然會致使主線程阻塞,從而使界面「假死」 dispatch_queue_t concurrentQueue = dispatch_queue_create("com.concurrentQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_queue_t serialQueue = dispatch_queue_create("com.serialQueue", DISPATCH_QUEUE_SERIAL); dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0); dispatch_sync(concurrentQueue, ^{ if ([NSThread isMainThread]) { NSLog(@"主線程"); }else{ NSLog(@"非主線程"); } //獲取當前時間,秒鐘 CFAbsoluteTime begin = CFAbsoluteTimeGetCurrent(); //整個管理文件或者文件夾 [[NSFileManager defaultManager] copyItemAtPath:@"/Users/zhouzhi/百度雲同步盤/電子專業書籍" toPath:@"/Users/zhouzhi/Desktop/電子書" error:nil]; //獲取結束時間點 CFAbsoluteTime end = CFAbsoluteTimeGetCurrent(); //打印消耗的時間 NSLog(@"%.2f秒", end - begin); }); NSLog(@"任務執行完成了");
除了同步提交任務到mainQueue會造成死鎖,其餘都是界面假死:說明只有同步向當前對列提交任務纔會形成死鎖