GCD:是4.0新增的,C語言寫的,他是蘋果公司爲多核CPU的並行運算提高效率出現的,能夠自動管理線程的生命週期,不需要我們對線程的管理。
1.任務和隊列
GCD的核心是任務和隊列的概念
任務:分爲同步任務sync順序執行,異步任務async開啓線成。
隊列:串行隊列 順序執行, 併發隊列 開啓線程。
2.相關API
1).隊列
全局主隊列系統提供(串行)
dispatch_queue_t queue = dispatch_get_main_queue()
全局併發隊列系統提供
/*參數一隊列優先級
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默認(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 後臺添加同步任務
參數二:隊列名稱 設爲0就好
*/
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
自定義創建隊列
/參數一:隊列表示符0表示
參數二:隊列類型
DISPATCH_QUEUE_SERIAL串行隊列
DISPATCH_QUEUE_COUNNET 並行隊列
/
dispatch_queue_t queue = dispatch_queue_creat(@“”,表示隊列類型)
2).創建任務
同步任務
dispatch_sync(queue,^{
//代碼
});
異步任務
dispatch_async(queue,^{
})
3.代碼測試
1.同步+串行隊列
//創建同步隊列 SERIAL串行隊列 COUNNET併發隊列
dispatch_queue_t queue = dispatch_queue_create("name", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
//執行代碼
for (NSInteger i=0; i<100; i++) {
NSLog(@"1--%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"2---%@",[NSThread currentThread]);
}
});
NSLog(@"結束迴歸主線程");
總結:同步+串行隊列 只有一個條線程,不會開啓新的線程。任務一個一個執行。
- 同步+併發
dispatch_queue_t queue1 = dispatch_queue_create("chuan", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue1, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"同步併發任務1---%@",[NSThread currentThread]);
}
});
dispatch_sync(queue1, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"同步併發任務2---%@",[NSThread currentThread]);
}
});
總結:同步+併發隊列 不開啓新線程,在主線程執行按順序執行
3.異步+串行
//創建串行隊列 serial串行
dispatch_queue_t queue2 = dispatch_queue_create("yibu", DISPATCH_QUEUE_SERIAL);
//創建異步任務
dispatch_async(queue2, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"異步串行任務1---%@",[NSThread currentThread]);
}
});
dispatch_async(queue2, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"異步串行任務2---%@",[NSThread currentThread]);
}
});
總結:異步任務+串行隊列 會開啓新線程,按順序執行
4.異步任務+並行隊列
//併發隊列
dispatch_queue_t queue3 = dispatch_queue_create("yi", DISPATCH_QUEUE_CONCURRENT);
//異步任務
dispatch_async(queue3, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"異步併發任務1---%@",[NSThread currentThread]);
//延遲操作
[NSThread sleepForTimeInterval:3];
}
});
dispatch_async(queue3, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"異步併發任務2---%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:5];
}
});
總結:異步任務+並行隊列 會開啓多條線程,任務同時執行,但是沒有順序,沒有順序,沒有順序
5.異步任務+並行隊列 按順序執行
需要使用柵欄函數
創建並行隊列
dispatch_queue_t queuebirrer = dispatch_queue_create("birrer", DISPATCH_QUEUE_CONCURRENT);
//創建同步任務
dispatch_async(queuebirrer, ^{
for (NSInteger i=0; i<5; i++) {
// NSLog(@"異步併發任務1---%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
}
});
//創建柵欄函數
dispatch_barrier_async(queuebirrer, ^{
for (NSInteger i=0; i<5; i++) {
// NSLog(@"異步併發柵欄函數任務2---%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
}
});
總結:使用柵欄函數可以使 異步任務+並行隊列按順序執行
6.主隊列(串行)+同步
dispatch_queue_t mainqueue = dispatch_get_main_queue(); //串行隊列
dispatch_sync(mainqueue, ^{
for (int i = 0; i < 4; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"主隊列+同步1---%@",[NSThread currentThread]);
}
});
dispatch_sync(mainqueue, ^{
for (int i = 0; i < 3; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"主隊列+同步2---%@",[NSThread currentThread]);
}
});
總結: 同步任務+串行主隊列 會堵塞主線程,程序崩潰,在其他線程不會奔潰
7.主隊列+異步任務
dispatch_queue_t mainqueue = dispatch_get_main_queue(); //串行隊列
dispatch_async(mainqueue, ^{
for (int i = 0; i < 4; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"主隊列+異步1---%@",[NSThread currentThread]);
}
});
dispatch_async(mainqueue, ^{
for (int i = 0; i < 4; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"主隊列+異步2---%@",[NSThread currentThread]);
}
});
總結:異步任務+主隊列 不開啓新線程,任務一個一個執行
8.線程間通信
線程間通信指的是子線程與主線程之間的通信
//全局併發隊列
dispatch_queue_t globorqQueue = dispatch_get_global_queue(0, 0);
//主隊列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(globorqQueue, ^{
for (int i = 0; i <10; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"全局併發隊列------%@",[NSThread currentThread]);
}
//迴歸主線程
dispatch_async(mainQueue, ^{
NSLog(@"線程執行完畢來兄弟告訴我執行玩了沒,玩了我就刷新控件了");
});
});
9.延遲函數 dispatch_after
延遲2秒執行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
});
10一次性函數 dispatch_once_t 經常用於創建單列
static dispatch_once_t onceKey;
dispatch_once(&onceKey, ^{
// manage = [[manage alloc]init];
});
11.隊列組 dispatch_group 當子線程異步任務執行完畢後,迴歸主線程
//創建隊列組
dispatch_group_t group = dispatch_group_create();
//創建全局併發隊列
dispatch_queue_t gqueue = dispatch_get_global_queue(0, 0);
//調用異步隊列組,參數一隊列組,參數二全局併發隊列
dispatch_group_async(group, gqueue, ^{
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"異步全局隊列組任務1---%@",[NSThread currentThread]);
}
});
dispatch_group_async(group, gqueue, ^{
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"異步全局隊列組任務2---%@",[NSThread currentThread]);
}
});
//上面任務執行完畢回到主線程:參數一:隊列組,參數二全局主隊列
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"好了你們子線程都執行完畢了該我主線程更新ui");
});
12.暫停線程 dispatch_wait 堵塞當前線程,等指定隊列組任務執行完畢纔會繼續執行
dispatch_group_t wgroup = dispatch_group_create();
dispatch_queue_t wqueue = dispatch_get_global_queue(0, 0);
dispatch_group_async(wgroup,wqueue, ^{
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"異步全局隊列組任務wait1---%@",[NSThread currentThread]);
}
});
dispatch_group_async(wgroup, wqueue, ^{
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"異步全局隊列組任務wait 2---%@",[NSThread currentThread]);
}
});
//DISPATCH_TIME_NOW(即使上面的隊列組中任務未完成也會執行下面的方法)
//DISPATCH_TIME_FOREVER 上面隊列組任務執行完畢以後纔會執行下面的方法
dispatch_group_wait(wgroup, DISPATCH_TIME_FOREVER);
NSLog(@"wait---上面執行完畢就是我了😄");
13.信號量dispatch_semaphore_t 主要作用解決線程同步的問題
個人理解當信號量大於1那麼繼續執行,小於1那麼堵塞不執行
dispatch_semaphroe_signal和dispatch_semaphore_wait成對出現
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
__block int number = 10;
//全局併發隊列
dispatch_queue_t queue9 = dispatch_get_global_queue(0, 0);
dispatch_async(queue9, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
for (int i = 0; i < 10; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"信號量---%@",[NSThread currentThread]);
}
number = 20;
//下面這個函數是當該線程執行完畢讓線程的信號量+1執行下面的方法,當不添加這句的話會不走下面的函數
dispatch_semaphore_signal(semaphore);
});