多執行緒——GCD

iOS_小賢發表於2019-01-23

標籤「iOS」「多執行緒」「GCD」

GCD的簡單使用

什麼是GCD

  • 全程是Grand Central Dispatch
  • 純C語言,提供非常多強大的函式
  • 多核並行運算,不叫多執行緒,它只是完成了多執行緒的封裝和使用

GCD的優勢

  • GCD是蘋果公司為多核的並行運算提出的解決方案;
  • iOS 4.0推出供開發者使用;
  • 使用GCD不關心執行緒,只要關心佇列;執行緒的排程是由CPU排程,那麼我們的CPU是有多核的。如果開發者去排程執行緒,那是否要考慮CPU的核數了?開發者是不是要考慮適配? 而你使用GCD,則不用動,所以開發者很便利。這就是蘋果多它的CPU多核伏筆
  • GCD 會自動利用更多的CPU核心(比如雙核、四核)
  • GCD會自動管理執行緒的生命週期(建立執行緒、排程任務、銷燬執行緒)
  • 程式設計師只需要告訴GCD想要執行什麼任務,不需要編寫任何執行緒管理程式碼

任務和佇列

GCD的2個核心概念

  • 任務:執行什麼操作
  • 佇列:用來存放任務

GCD的使用就2個步驟

  • 定製任務(確定想做的事情) 將大象放進冰箱有幾步?
  • 將任務新增到佇列中

GCD會自動將==佇列==中的==任務==取出,放到對應的==執行緒==中執行; 任務的取出遵循物件的==FIFO原則:先進先出,後進後出==

==畫圖分析== 程式設計師要做的,將任務新增到佇列;佇列按照程式設計師指定的方式,排程任務。執行任務的方法:同步/非同步 同步:一個任務沒有結束,就不會執行下一個任務 非同步:不用等待任務執行完畢,就會執行下一個任務

GCD有一個“執行緒池”;

  • GCD同步排程任務時,會拿出1根執行緒,讓它執行佇列中的任務。當一個任務執行完成後,就會再從佇列一個一個的執行;
  • GCD非同步排程任務時,首先拿出1根執行緒,讓這個執行緒去處理一個任務;當任務開始執行,就再從執行緒池裡,再獲取一個執行緒去佇列去順序拿任務執行;指定執行緒最大併發數;當其中的執行緒執行任務完畢後,再去佇列中按照FIFO原則獲取任務;

圖1:同步執行緒圖例

image.png

圖2:非同步執行緒圖例

image.png

==例項demo 001GCD程式碼演示==

在viewController 的touchBegain方法裡去呼叫方法。[self gcdDemo1]

  • 在viewController裡,gcdDemo1方法:

1.建立佇列 2.新增任務到佇列中 3.將任務新增到佇列,並且會執行

寫block的方法的竅門:寫用函式的思路寫出,太函式名前面加一個括號()和 尖尖符號,再在函式體外面的大括號{}前面加一個尖尖符號

/*
同步執行方法,這句話不執行完,就不會執行下個任務,同步執行不會開啟執行緒;
*/
-(void)gcdDemo1
{
    //1.建立佇列
    dispatch_queue_t q = dispatch_get_global_queue(0,0);
    //2.任務新增到佇列中
    //2.1定義任務--block
    void (^task)() = ^{
        NSLog(@"%@",[NSThread curresntThread]);
    };
    //2.2 新增任務到佇列,並且會執行
    dispatch_sync(q,task);

    //合併步驟1,2步,省略寫法
    dispatch_sync(q,^{
    NSLog(@"%@",[NSThread currentThread]);
    });

}

複製程式碼
  • 在viewController裡非同步執行任務,gcdDemo2方法:

1.建立佇列 2.新增任務到佇列中 3.將任務新增到非同步佇列,並且會執行

非同步執行,如果任務沒有執行完畢,可以不用等待;非同步執行下一個任務。具備開啟執行緒的能力,非同步通常又是多執行緒的代名詞!

/*
非同步任務
*/
-(void)gcdDemo2
{
    //1.建立佇列
    dispatch_queue_t q = dispatch_get_global_queue(0,0);
    //2.1定義任務--block
    void (^task)() = ^{
        NSLog(@"%@",[NSThread curresntThread]);
    };
    //2.2 新增任務到佇列,並且會執行
    dispatch_async(q,task);

}

複製程式碼

執行緒間的通訊

GCD之間的執行緒通訊

-(void)gcdDemo3
{
    //指定任務執行方法 -- 非同步
    dispatch_async(dispatch_get_global_queue(0,0),^{

    //耗時操作
    NSLog(@"%@",[NSThread currentThread]);

    //更新UI
    dispatch_async(dispatch_get_main_Queue(),^{
        NSLog(@"更新UI%@",[NSThread currentThread]);
    });

    });
}

複製程式碼

==修改多執行緒demo 002--顯示網路圖片==

-(void)viewDidLoad
{
   //程式碼集中,便於維護
    //利用GCD獲取網路圖片
    //非同步執行
    dispatch_async(dispatch_get_global_queue(0,0),^{

    NSURL *url = [NSURL URLWithString:@"http://img3.utuku.china.com/395x0/news/20170629/35381bbe-6e16-4be1-8cf4-4af9107448b7.jpg"];
    NSData *data = [NSData dataWithContentsOfURL:url];
    UIImage *image = [UIImage imageWithData:data];

    //更新UI
    dispatch_async(dispatch_get_main_queue(),^{
        self.imageView.image = image;
        [self.imageView sizeToFit];
        self.scrollView.contentSize = image.size;
    });

    //block沒有迴圈引用,只是一個程式碼塊,因為它沒有作為屬性,這裡的block用完就釋放了。
    });
}
複製程式碼

讓一切儘可能簡單,但不是愚蠢。  ——  阿爾伯特·愛因斯坦

關注微信公眾號:iOSSir,每日更新蘋果資訊、技術乾貨!

image.png

相關文章