多線程-GCD

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(@"結束迴歸主線程");

總結:同步+串行隊列 只有一個條線程,不會開啓新的線程。任務一個一個執行。

  1. 同步+併發
 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);
    });

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章