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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

GCD是當(dāng)前多線程使用最方便的,也是使用比較多的。

學(xué)習(xí)GCD主要集中在一下幾點:

一、隊列,同步,異步

1.主隊列:dispatch_get_main_queue();

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

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

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

?

對上面關(guān)鍵詞的一些解釋:

主隊列:主隊列只能使用異步來執(zhí)行隊列中的任務(wù),使用同步的話會造成死循環(huán)。同時執(zhí)行任務(wù)的時候是在主線程中執(zhí)行的。

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

??????????????????????? 但是可以創(chuàng)建多個串行隊列,每個串行隊列之間是相互獨(dú)立的,可以并發(fā)執(zhí)行。

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

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

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

??????????????????????? 并行隊列也可以創(chuàng)建多個,各個之間也是相互獨(dú)立,并發(fā)執(zhí)行的。

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

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

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

二、經(jīng)常用到的地方

1.任務(wù)執(zhí)行完畢之后再進(jìn)行一些操作

2.只執(zhí)行一次

3.延時操作

?

對上面用處的一些解釋:

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

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


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

?

(2)、只執(zhí)行一次

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

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

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

});

?

(3)、延時操作

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

??????? ? //延遲執(zhí)行的方法

??? });

?

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

dispatch_suspend和dispatch_resume

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

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

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

這些函數(shù)不會影響到隊列中已經(jīng)執(zhí)行的任務(wù),隊列暫停后,已經(jīng)添加到隊列中但還沒有執(zhí)行的任務(wù)不會執(zhí)行,直到隊列被恢復(fù)。

?

(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?會把并行隊列的運(yùn)行周期分為這三個過程:

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

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

    ?

    (6)、信號量

    dispatch_semaphore

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

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

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

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

    在GCD中,創(chuàng)建信號量的語法如下:

    var?semaphore = dispatch_semaphore_create(2) ?

    這句代碼通過?dispatch_semaphore_create?方法創(chuàng)建一個信號量并設(shè)置初始值為 2。然后就可以調(diào)用?dispatch_semaphore_wait?方法了。

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) ?

    dispatch_semaphore_wait?方法表示一直等待直到信號量的值大于等于 1,當(dāng)這個方法執(zhí)行后,會把第一個信號量參數(shù)的值減 1。

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

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

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

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

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

    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

    ? ? ? ??/*

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

    ? ? ? ? ? ? 與此同時,因為信號量變?yōu)?,其它執(zhí)行到這里的線程都必須等待

    ? ? ? ? */

    ? ? ? ? dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)

    ?

    ? ? ? ??/*

    ? ? ? ? ? ? 執(zhí)行了wait方法后,信號量的值變成了0。可以進(jìn)行接下來的操作。

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

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

    ? ? ? ? */

    ? ? ? ? array.append(i)

    ?

    ? ? ? ??/*

    ? ? ? ? ? ? 排他操作執(zhí)行結(jié)束,記得要調(diào)用signal方法,把信號量的值加1。

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

    ? ? ? ? */

    ? ? ? ? dispatch_semaphore_signal(semaphore)

    ? ? })

    }

    ?

    總結(jié):

    1、常用的延時操作:

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

    ??????? ? //延遲執(zhí)行的方法

    ??? });

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

    2、回到主線程的操作:

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

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

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

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/danMing-love/p/5598361.html

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。