日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

关于多线程之GCD的一些学习要点

發布時間:2023/12/10 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于多线程之GCD的一些学习要点 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

GCD是當前多線程使用最方便的,也是使用比較多的。

學習GCD主要集中在一下幾點:

一、隊列,同步,異步

1.主隊列:dispatch_get_main_queue();

2.串行隊列:dispatch_queue_create("queue", 0);

3.并行隊列:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

4.同步,異步就不需要再多說什么。

?

對上面關鍵詞的一些解釋:

主隊列:主隊列只能使用異步來執行隊列中的任務,使用同步的話會造成死循環。同時執行任務的時候是在主線程中執行的。

串行隊列:(1)、添加到串行隊列中的任務是一個接著一個執行的,也就是當上一個任務執行完之后才開始下一個任務;

??????????????????????? 但是可以創建多個串行隊列,每個串行隊列之間是相互獨立的,可以并發執行。

???????????? ?(2)、如果用同步執行的話就是在當前線程上執行;

????????????? (3)、如果用異步執行的話就是新開辟一個線程執行。

并行隊列:(1)、添加到并行隊列中的任務可以并發啟動,啟動順序仍然是一個接著一個,但是后者可以不等前者執行完就可以開始執行。

??????????????????????? 并行隊列也可以創建多個,各個之間也是相互獨立,并發執行的。

???????????? ?(2)、如果用同步執行的話就是在當前線程上執行;

????????????? (3)、如果用異步執行的話就是新開辟一個線程執行。

????????????

二、經常用到的地方

1.任務執行完畢之后再進行一些操作

2.只執行一次

3.延時操作

?

對上面用處的一些解釋:

(1)、任務執行完畢之后再進行一些操作,如果是一些簡單的操作可以直接使用串行隊列實現。但是一些比較費時的操作就需要用到隊列組了。

??? //1.創建一個隊列組
??????? dispatch_group_t group = dispatch_group_create();
????
??? //2.開啟一個任務1
??? dispatch_group_async(group, global_quque, ^{
?
??? });
????
??? //3.開啟一個任務2
??? dispatch_group_async(group, global_quque, ^{


?????? });
????
?? //4.等group中的所有任務都執行完畢, 再回到主線程執行其他操作
??? dispatch_group_notify(group,main_queue, ^{
???? });
????

?

(2)、只執行一次

????????? static dispatch_once_t onceToken;

????????? dispatch_once(&onceToken, ^{

????? ??? // 只執行1次的代碼(這里面默認是線程安全的)

});

?

(3)、延時操作

????????? dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

??????? ? //延遲執行的方法

??? });

?

(4)、暫停和恢復隊列中的任務

dispatch_suspend和dispatch_resume

我們知道NSOperationQueue有暫停(suspend)和恢復(resume)。其實GCD中的隊列也有類似的功能。用法也非常簡單:

dispatch_suspend(queue)?//暫停某個隊列 ?

dispatch_resume(queue)??//恢復某個隊列 ?

這些函數不會影響到隊列中已經執行的任務,隊列暫停后,已經添加到隊列中但還沒有執行的任務不會執行,直到隊列被恢復。

?

(5)、承上啟下

dispatch_async(queue, block1_for_reading) ?

dispatch_async(queue, block2_for_reading)

?

dispatch_barrier_async(queue, block_for_writing)

?

dispatch_async(queue, block3_for_reading) ?

dispatch_async(queue, block4_for_reading) ?

dispatch_barrier_async?會把并行隊列的運行周期分為這三個過程:

  • 首先等目前追加到并行隊列中所有任務都執行完成
  • 開始執行?dispatch_barrier_async?中的任務,這時候即使向并行隊列提交任務,也不會執行
  • dispatch_barrier_async?中的任務執行完成后,并行隊列恢復正常。
  • 總的來說,dispatch_barrier_async?起到了“承上啟下”的作用。它保證此前的任務都先于自己執行,此后的任務也遲于自己執行。正如barrier的含義一樣,它起到了一個柵欄、或是分水嶺的作用。

    這樣一來,使用并行隊列和?dispatc_barrier_async?方法,就可以高效的進行數據和文件讀寫了。

    ?

    (6)、信號量

    dispatch_semaphore

    首先介紹一下信號量(semaphore)的概念。信號量是持有計數的信號,不過這么解釋等于沒解釋。我們舉個生活中的例子來看看。

    假設有一個房子,它對應進程的概念,房子里的人就對應著線程。一個進程可以包括多個線程。這個房子(進程)有很多資源,比如花園、客廳等,是所有人(線程)共享的。

    但是有些地方,比如臥室,最多只有兩個人能進去睡覺。怎么辦呢,在臥室門口掛上兩把鑰匙。進去的人(線程)拿著鑰匙進去,沒有鑰匙就不能進去,出來的時候把鑰匙放回門口。

    這時候,門口的鑰匙數量就稱為信號量(Semaphore)。很明顯,信號量為0時需要等待,信號量不為零時,減去1而且不等待。

    在GCD中,創建信號量的語法如下:

    var?semaphore = dispatch_semaphore_create(2) ?

    這句代碼通過?dispatch_semaphore_create?方法創建一個信號量并設置初始值為 2。然后就可以調用?dispatch_semaphore_wait?方法了。

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) ?

    dispatch_semaphore_wait?方法表示一直等待直到信號量的值大于等于 1,當這個方法執行后,會把第一個信號量參數的值減 1。

    第二個參數是一個?dispatch_time_t?類型的時間,它表示這個方法最大的等待時間。這在第一章中已經講過,比如?DISPATCH_TIME_FOREVER?表示永久等待。

    返回值也和?dispatch_group_wait?方法一樣,返回 0 表示在規定的等待時間內第一個參數信號量的值已經大于等于 1,否則表示已超過規定等待時間,但信號量的值還是 0。

    dispatch_semaphore_wait?方法返回 0,因為此時的信號量的值大于等于一,任務獲得了可以執行的權限。這時候我們就可以安全的執行需要進行排他控制的任務了。

    任務結束時還需要調用?dispatch_semaphore_signal()?方法,將信號量的值加 1。這類似于之前所說的,從臥室出來要把鎖放回門上,否則后來的人就無法進入了。

    我們來看一個完整的例子:

    var?semaphore = dispatch_semaphore_create(1) ?

    let?queue = dispatch_queue_create("com.gcd.kt", DISPATCH_QUEUE_CONCURRENT) ?

    var?array: [Int] = []

    ?

    for?i?in?1...100000?{ ?

    ? ? dispatch_async(queue, { () -> Void?in

    ? ? ? ??/*

    ? ? ? ? ? ? 某個線程執行到這里,如果信號量值為1,那么wait方法返回1,開始執行接下來的操作。

    ? ? ? ? ? ? 與此同時,因為信號量變為0,其它執行到這里的線程都必須等待

    ? ? ? ? */

    ? ? ? ? dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)

    ?

    ? ? ? ??/*

    ? ? ? ? ? ? 執行了wait方法后,信號量的值變成了0。可以進行接下來的操作。

    ? ? ? ? ? ? 這時候其它線程都得等待wait方法返回。

    ? ? ? ? ? ? 可以對array修改的線程在任意時刻都只有一個,可以安全的修改array

    ? ? ? ? */

    ? ? ? ? array.append(i)

    ?

    ? ? ? ??/*

    ? ? ? ? ? ? 排他操作執行結束,記得要調用signal方法,把信號量的值加1。

    ? ? ? ? ? ? 這樣,如果有別的線程在等待wait函數返回,就由最先等待的線程執行。

    ? ? ? ? */

    ? ? ? ? dispatch_semaphore_signal(semaphore)

    ? ? })

    }

    ?

    總結:

    1、常用的延時操作:

    ??? (1)????dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

    ??????? ? //延遲執行的方法

    ??? });

    ??? (2) ? [self performSelector:@selector(test) withObject:nil afterDelay:1.0];

    2、回到主線程的操作:

    ??? (1)??? dispatch_async(dispatch_get_main_queue(), ^{

    ?????????????? // 回到主線程,執?UI刷新操作 });

    ??? (2)??? [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];

    ?

    轉載于:https://www.cnblogs.com/danMing-love/p/5598361.html

    總結

    以上是生活随笔為你收集整理的关于多线程之GCD的一些学习要点的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。