多線程(GCD)

多線程(GCD)

GCD的基本使用

  • GCD是蘋果為多核并行運算提出的解決方案
  • GCD會自動利用更多的內(nèi)核
  • GCD同NSOperation一樣,也會自動管理線程的生命周期
  • GCD是C的代碼,較NSOperation性能更高
  • GCD也是以隊列的形式工作,FIFO
  • 基本用法
    //線程間通信
    //進(jìn)入子線程進(jìn)行耗時操作
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@",[NSThread currentThread]);
        //回主線程進(jìn)行刷新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"%@",[NSThread currentThread]);
        });
    });

GCD的兩種隊列

  • 并發(fā)隊列(ConcurrentQueue):可以并發(fā)執(zhí)行多個任務(wù),允許開啟多個線程同時執(zhí)行任務(wù)(只是允許,要根據(jù)是否具有開啟新線程的能力),所以只有異步函數(shù)才會對并發(fā)隊列起作用,
  • 串行隊列(SerialQueue):讓任務(wù)一個接著一個的執(zhí)行,
    • GCD自帶一個特殊的串行隊列為主隊列,主隊列自動會放到主線程中執(zhí)行
    • GCD還自帶一個全局的并發(fā)隊列,可以設(shè)置優(yōu)先級(dispatch_get_global_queue)

同步和異步

  • 同步:只能在當(dāng)前線程中執(zhí)行任務(wù),不具備開啟新線程的能力
  • 異步:具備開啟新線程的能力
同步 異步
串行 沒有開啟線程,串行執(zhí)行任務(wù) 開啟一條線程,串行執(zhí)行任務(wù)
并發(fā) 沒有開啟線程,串行執(zhí)行任務(wù) 開啟線程(大于等于1條,不受控制),并發(fā)執(zhí)行任務(wù)

各種函數(shù)隊列演示代碼

同步串行(打印結(jié)果12345)

//創(chuàng)建一個串行隊列
    dispatch_queue_t queue = dispatch_queue_create("duilie", DISPATCH_QUEUE_SERIAL);
//創(chuàng)建一個并行隊列
    dispatch_queue_t queeu = dispatch_queue_create("bbb", DISPATCH_QUEUE_CONCURRENT);
    //同步執(zhí)行這個串行隊列(順序執(zhí)行,不會創(chuàng)建新的線程)
    dispatch_sync(queue, ^{
        NSLog(@"1%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"4%@",[NSThread currentThread]);
    });
    NSLog(@"5%@",[NSThread currentThread]);

同步并行(打印結(jié)果12345)

    //同步執(zhí)行一個并行隊列(順序執(zhí)行,沒有開啟線程,只是允許并行執(zhí)行,但是沒有線程這個條件,實際還是串行執(zhí)行)
    dispatch_sync(queeu, ^{
        NSLog(@"1%@",[NSThread currentThread]);
    });
    dispatch_sync(queeu, ^{
        NSLog(@"2%@",[NSThread currentThread]);
    });
    dispatch_sync(queeu, ^{
        NSLog(@"3%@",[NSThread currentThread]);
    });
    dispatch_sync(queeu, ^{
        NSLog(@"4%@",[NSThread currentThread]);
    });
    NSLog(@"5%@",[NSThread currentThread]);

異步串行(打印結(jié)果1234,5不一定插在1234的哪個位置,因為1234和5是并行的,1234是串行的)

    //異步執(zhí)行這個串行隊列(1234順序執(zhí)行,5和1234并行,開啟一條線程,)
    dispatch_async(queue, ^{
        NSLog(@"1%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"4%@",[NSThread currentThread]);
    });
    NSLog(@"5%@",[NSThread currentThread]);

異步并行(打印結(jié)果隨機,12345五個任務(wù)執(zhí)行都是并發(fā))

    //異步執(zhí)行一個并行隊列(主線程和其他線程一起執(zhí)行,順序不一定,開啟的線程數(shù)也不一定)
    dispatch_async(queeu, ^{
        NSLog(@"1%@",[NSThread currentThread]);
    });
    dispatch_async(queeu, ^{
        NSLog(@"2%@",[NSThread currentThread]);
    });
    dispatch_async(queeu, ^{
        NSLog(@"3%@",[NSThread currentThread]);
    });
    dispatch_async(queeu, ^{
        NSLog(@"4%@",[NSThread currentThread]);
    });
    NSLog(@"5%@",[NSThread currentThread]);

系統(tǒng)提供的五種隊列(1主隊列 + 4全局子隊列)

    //1.當(dāng)前隊列的優(yōu)先級2.沒用
    /**
     * DISPATCH_QUEUE_PRIORITY_HIGH 2
     * DISPATCH_QUEUE_PRIORITY_DEFAULT 0
     * DISPATCH_QUEUE_PRIORITY_LOW (-2)
     * DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
     */
    //獲取到全局子隊列
    dispatch_queue_t qq = dispatch_get_global_queue(0, 0);
    //獲取主隊列
    dispatch_queue_t q =  dispatch_get_main_queue();

GCD的其他函數(shù)

  • 延時執(zhí)行
 //延時執(zhí)行
    //參數(shù):幾秒后執(zhí)行(填的是2,代表兩秒后執(zhí)行)
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"延遲執(zhí)行的代碼片段");
    });
    NSLog(@"我先走了");
  • 只執(zhí)行一次(線程安全,只有創(chuàng)建單例用它,其他地方不要用)
    //只執(zhí)行一次(線程安全的)
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"只走一次");
    });
  • 重復(fù)執(zhí)行
 //重復(fù)執(zhí)行
    //1.重復(fù)的次數(shù) 2.在什么隊列重復(fù) 3.當(dāng)前次數(shù)的索引
    dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t a) {
        NSLog(@"%zu",a);
    }) ;
  • 線程組
    • 本質(zhì)是先把任務(wù)放到隊列中,再把隊列放入組內(nèi)
    • 優(yōu)點:可以監(jiān)聽組內(nèi)的任務(wù)完畢
//創(chuàng)建一個組(先把任務(wù)放進(jìn)隊列里,在放進(jìn)組里,組可以監(jiān)聽任務(wù)完畢)
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"任務(wù)1");
    });
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"任務(wù)2");
    });
    //監(jiān)聽組內(nèi)執(zhí)行情況(監(jiān)聽組內(nèi)所有隊列執(zhí)行完畢)
    dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"執(zhí)行完畢");
    });
  • 單獨執(zhí)行(dispatch_barrier_async)
    • 本質(zhì)是在并發(fā)隊列中擁有串行的權(quán)利
    • 如果有12345個任務(wù),給3任務(wù)設(shè)置單獨執(zhí)行,按照12345的順序添加任務(wù),那么一定是12執(zhí)行完才會執(zhí)行3,3執(zhí)行完才會執(zhí)行45,所以12和45在執(zhí)行的時候是并發(fā),但是到了3,12和3和45其實是串行的
    • 注意:如果想要這樣設(shè)置其執(zhí)行順序(其實是仿照NSOperation設(shè)置依賴),那么所在的隊列一定不能是系統(tǒng)提供的全局并發(fā)隊列
    //創(chuàng)建并發(fā)隊列
    dispatch_queue_t tt = dispatch_queue_create("tt", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(tt, ^{
        NSLog(@"任務(wù)1");
    });
    dispatch_async(tt, ^{
        NSLog(@"任務(wù)2");
    });
    //單獨執(zhí)行
    dispatch_barrier_sync(tt, ^{
        NSLog(@"任務(wù)3");
    });
    dispatch_async(tt, ^{
        NSLog(@"任務(wù)4");
    });
    dispatch_async(tt, ^{
        NSLog(@"任務(wù)5");
    });
  • block變成函數(shù)執(zhí)行
    • 本質(zhì)是將block塊變成c語言的函數(shù),兩種方式是一樣的(dispatch_async和dispatch_async_f)
 dispatch_async_f(dispatch_get_global_queue(0, 0), @"1", sum);
- void sum (void *a)
{
    NSLog(@"%@",a);
}

資源搶奪

  • 再實際開發(fā)過程中會將常出現(xiàn)賣票效應(yīng),其實就是多個線程訪問同一個實例變量,并改變實例變量的值,就會導(dǎo)致實例變量的值發(fā)生錯誤,
  • 互斥鎖(@synchronized)有效的解決了這個問題
  • 互斥鎖原理:使用了線程同步技術(shù),多條線程在同一條線上執(zhí)行,并且按順序執(zhí)行
  • 將要訪問的實例變量套用在互斥鎖里面
    int a = 1000;
    //資源搶奪(對象)
    //互斥鎖帶的參數(shù)一定要傳一個對象,一般情況傳self
    @synchronized(self) {
        //鎖的是代碼
        a = a - 1;
    }
  • 互斥鎖的缺點:會消耗大量的CPU資源
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子扒腕,更是在濱河造成了極大的恐慌义锥,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岩灭,死亡現(xiàn)場離奇詭異拌倍,居然都是意外死亡,警方通過查閱死者的電腦和手機噪径,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門柱恤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人找爱,你說我怎么就攤上這事梗顺。” “怎么了车摄?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵寺谤,是天一觀的道長。 經(jīng)常有香客問我吮播,道長变屁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任意狠,我火速辦了婚禮粟关,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘环戈。我一直安慰自己闷板,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布院塞。 她就那樣靜靜地躺著蛔垢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪迫悠。 梳的紋絲不亂的頭發(fā)上鹏漆,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機與錄音创泄,去河邊找鬼艺玲。 笑死,一個胖子當(dāng)著我的面吹牛鞠抑,可吹牛的內(nèi)容都是我干的饭聚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼搁拙,長吁一口氣:“原來是場噩夢啊……” “哼秒梳!你這毒婦竟也來了法绵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤酪碘,失蹤者是張志新(化名)和其女友劉穎朋譬,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兴垦,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡徙赢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了探越。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狡赐。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖钦幔,靈堂內(nèi)的尸體忽然破棺而出枕屉,到底是詐尸還是另有隱情,我是刑警寧澤鲤氢,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布搀擂,位于F島的核電站,受9級特大地震影響铜异,放射性物質(zhì)發(fā)生泄漏哥倔。R本人自食惡果不足惜秸架,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一揍庄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧东抹,春花似錦蚂子、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至馏谨,卻和暖如春别渔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背惧互。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工哎媚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人喊儡。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓拨与,卻偏偏與公主長得像,于是被迫代替她去往敵國和親艾猜。 傳聞我的和親對象是個殘疾皇子买喧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容

  • #import "ViewController.h" @interface ViewController () @...
    艾克12138閱讀 216評論 0 0
  • 目錄 一捻悯、基本概念1.多線程2.串行和并行, 并發(fā)3.隊列與任務(wù)4.同步與異步5.線程狀態(tài)6.多線程方案 二淤毛、GC...
    BohrIsLay閱讀 1,583評論 5 12
  • 最近頗花了一番功夫把多線程GCD人的一些用法總結(jié)出來今缚,一來幫自己鞏固一下知識、二來希望能幫到對這一塊還迷茫...
    人活一世閱讀 290評論 1 1
  • 一钱床、簡介在iOS所有實現(xiàn)多線程的方案中荚斯,GCD應(yīng)該是最有魅力的,因為GCD本身是蘋果公司為多核的并行運算提出的解決...
    MYS_iOS_8801閱讀 572評論 0 0
  • 2017年10月21日,我與簡書相遇了纸颜。 因為偶然間在某知名自媒體人的簡歷里看到她是一名簡書簽約作者兽泣,于是抱著好奇...
    伊文說閱讀 1,419評論 37 22