iOS多線程GCD詳解

 

咱們在這裏複習下GCD。git

1.什麼是GCD?

GCD全稱Grand Central Dispatch,咱們通俗的翻譯叫牛逼的中心調度。github

2.咱們用GCD幹什麼?

經過 GCD,開發者不用再直接跟線程打交道了,只須要向隊列中添加代碼塊便可,GCD 在後端管理着一個線程池。GCD 不只決定着你的代碼塊將在哪一個線程被執行,它還根據可用的系統資源對這些線程進行管理。這樣能夠將開發者從線程管理的工做中解放出來,經過集中的管理線程,來緩解大量線程被建立的問題。後端

GCD 帶來的另外一個重要改變是,做爲開發者能夠將工做考慮爲一個隊列,而不是一堆線程,這種並行的抽象模型更容易掌握和使用。多線程

首先,系統提供給你一個叫作 主隊列(main queue) 的特殊隊列。和其它串行隊列同樣,這個隊列中的任務一次只能執行一個。然而,它能保證全部的任務都在主線程執行,而主線程是惟一可用於更新 UI 的線程。這個隊列就是用於發生消息給 UIView 或發送通知的。併發

系統同時提供給你好幾個併發隊列。它們叫作 全局調度隊列(Global Dispatch Queues) 。目前的四個全局隊列有着不一樣的優先級:background、low、default 以及 high。要知道,Apple 的 API 也會使用這些隊列,因此你添加的任何任務都不會是這些隊列中惟一的任務。app

最後,你也能夠建立本身的串行隊列或併發隊列。這就是說,至少有五個隊列任你處置:主隊列、四個全局調度隊列,再加上任何你本身建立的隊列。異步

3.GCD相比其餘多線程有哪些優勢?

  • GCD 能經過推遲昂貴計算任務並在後臺運行它們來改善你的應用的響應性能。
  • GCD 提供一個易於使用的併發模型而不單單只是鎖和線程,以幫助咱們避開併發陷阱。
  • GCD 具備在常見模式(例如單例)上用更高性能的原語優化你的代碼的潛在能力。
  • GCD 會自動利用更多的CPU內核(好比雙核、四核)

4.GCD術語

  • 串行(Serial):讓任務一個接着一個地執行(一個任務執行完畢後,再執行下一個任務)
  • 併發(Concurrent):可讓多個任務併發(同時)執行(自動開啓多個線程同時執行任務)併發功能只有在異步(dispatch_async)函數下才有效。
  • 同步(Synchronous):在當前線程中執行任務,不具有開啓新線程的能力
  • 異步(Asynchronous):在新的線程中執行任務,具有開啓新線程的能力

5.使用GCD

1.認識主隊列,感覺串行隊列的運行,運行結果打印的是 1,2,3,4,順序執行。async

1
2
3
4
5
6
7
8
9
10
11
12
13
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
NSLog(@"1");
});
dispatch_async(mainQueue, ^{
NSLog(@"2");
});
dispatch_async(mainQueue, ^{
NSLog(@"3");
});
dispatch_async(mainQueue, ^{
NSLog(@"4");
});

2.認識全局隊列,體驗併發隊列的運行,運行結果隨機打印:2,3,1,4,隨機執行。函數

1
2
3
4
5
6
7
8
9
10
11
12
13
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(defaultQueue, ^{
NSLog(@"1");
});
dispatch_async(defaultQueue, ^{
NSLog(@"2");
});
dispatch_async(defaultQueue, ^{
NSLog(@"3");
});
dispatch_async(defaultQueue, ^{
NSLog(@"4");
});

3.建立自定義隊列性能

1
2
3
4
5
6
7
8
9
10
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.bjsxt.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(concurrentQueue, ^{
NSLog(@"4");
dispatch_sync(concurrentQueue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"5");
});
NSLog(@"6");
});

4.GCD在單例中的運用dispatch_once

1
2
3
4
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"onceToken");
});

5.延遲加載dispatch_after

1
2
3
4
5
6
double delayInSeconds = 2.0;
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW,delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, mainQueue, ^{
NSLog(@"延時執行的2秒");
});

6.調度組dispatch_group_t

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, defaultQueue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"1");
});
dispatch_group_async(group, defaultQueue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2");
});
dispatch_group_notify(group, defaultQueue, ^{
NSLog(@"3");
});

//等價於

// dispatch_group_enter(group);
// dispatch_async(defaultQueue, ^{
//
// NSLog(@"1");
// dispatch_group_leave(group);
// });

7.dispatch_barrier_async

在前面的任務執行結束後它才執行,並且它後面的任務等它執行完成以後纔會執行.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
dispatch_queue_t queue = dispatch_queue_create("com.bjsxt.barrierExecute", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:4];
NSLog(@"2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"3");
[NSThread sleepForTimeInterval:4];

});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"4");
});

8.執行某個代碼dispatch_apply

1
2
3
4
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(5, defaultQueue, ^(size_t i) {
NSLog(@"%lu",i);
});

參考文章:

https://github.com/nixzhu/dev-blog

http://objccn.io/issue-2-1/

另外.....

個人願望是.......

世界和平.........

相關文章
相關標籤/搜索