iOS多線程

轉(zhuǎn)載請注明出處:http://www.reibang.com/p/ffd1f7a5db20
作者:紀(jì)小衰
參考資料:http://www.cocoachina.com/ios/20160804/17291.html

同步:多個(gè)任務(wù)情況下,一個(gè)任務(wù)A執(zhí)行結(jié)束伙判,才可以執(zhí)行另一個(gè)任務(wù)B象对。只存在一個(gè)線程也就是主線程。 異步:多個(gè)任務(wù)情況下宴抚,一個(gè)任務(wù)A正在執(zhí)行勒魔,同時(shí)可以執(zhí)行另一個(gè)任務(wù)B。任務(wù)B不用等待任務(wù)A結(jié)束才執(zhí)行菇曲。

并行:指兩個(gè)或多個(gè)時(shí)間在同一時(shí)刻發(fā)生冠绢。多核CUP同時(shí)開啟多條線程供多個(gè)任務(wù)同時(shí)執(zhí)行,互不干擾羊娃。 并發(fā):指兩個(gè)或多個(gè)事件在同一時(shí)間間隔內(nèi)發(fā)生唐全。可以在某條線程和其他線程之間反復(fù)多次進(jìn)行上下文切換蕊玷,看上去就好像一個(gè)CPU能夠并且執(zhí)行多個(gè)線程一樣邮利。其實(shí)是偽異步。

多線程編程會(huì)導(dǎo)致的問題:
1.數(shù)據(jù)競爭
2.死鎖
3.內(nèi)存消耗和線程切換cpu消耗

使用多線程的必要性: 主線程中會(huì)描繪用戶界面和處理觸摸事件垃帅,如果在主線程中進(jìn)行長事件處理會(huì)導(dǎo)致主線程阻塞延届,妨礙主線程的RunLoop主循環(huán)的執(zhí)行

GCD的使用: 蘋果官方對GCD是這樣說明的:開發(fā)者要做的只是定義想執(zhí)行的任務(wù)并追加到適當(dāng)?shù)腄ispatch Queue中。Dispatch Queue是按照追加的順序 進(jìn)行處理贸诚,先進(jìn)先出FIFO方庭。

Serial Dispatch Queue串行調(diào)度隊(duì)列:等待現(xiàn)在執(zhí)行中的事件處理結(jié)束再執(zhí)行下一個(gè)任務(wù)。多個(gè)串行隊(duì)列可以并發(fā)執(zhí)行酱固,但是創(chuàng)建多個(gè)線程的消耗會(huì)比較大械念,此時(shí)考慮使用并行隊(duì)列

Concurrent Dispatch Queue并發(fā)調(diào)度隊(duì)列:不等待現(xiàn)在執(zhí)行中的事件處理結(jié)束就可以開始下一個(gè)任務(wù)

//創(chuàng)建串行隊(duì)列
dispatch_queue_t queue1 = dispatch_queue_create("com.jr1", DISPATCH_QUEUE_SERIAL);
//創(chuàng)建并行隊(duì)列
dispatch_queue_t queue2 = dispatch_queue_create("com.jr1", DISPATCH_QUEUE_CONCURRENT);
//獲取系統(tǒng)的主隊(duì)列 (Main Dispatch Queue是在主線程中執(zhí)行的Dispatch Queue,也就是Serial Dispatch Queue)
dispatch_queue_t queue3 = dispatch_get_main_queue();
//獲取全局隊(duì)列 (param:優(yōu)先級运悲,保留字段 type:concurrent)
dispatch_queue_t queue4 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t queue5 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t queue6 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_queue_t queue7 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

//重新設(shè)置隊(duì)列的優(yōu)先級
dispatch_queue_t newBackQueue = dispatch_queue_create("backQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t backGroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(newBackQueue, backGroundQueue);

//程序執(zhí)行過程中只執(zhí)行一次的隊(duì)列
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    
});

//延遲執(zhí)行 延遲執(zhí)行指在多長時(shí)間以后追加到隊(duì)列中龄减,而不是執(zhí)行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

});

//3.1串行隊(duì)列同步執(zhí)行 輸出:1 2 3
dispatch_queue_t q1 = dispatch_queue_create("com.jr1", DISPATCH_QUEUE_SERIAL);
dispatch_async(q1, ^{
    sleep(1);
    NSLog(@"SERIA_ASYNC_1");
});
dispatch_async(q1, ^{
    sleep(0.5);
    NSLog(@"SERIA_ASYNC_2");
});
dispatch_async(q1, ^{
    sleep(0.2);
    NSLog(@"SERIA_ASYNC_3");
});

//3.2串行隊(duì)列同步執(zhí)行 輸出 :1 2 3
dispatch_queue_t q2 = dispatch_queue_create("com.jr2", DISPATCH_QUEUE_SERIAL);
dispatch_sync(q2, ^{
    sleep(1);
    NSLog(@"SERIAL_SYNC_1");
});
dispatch_sync(q2, ^{
    sleep(0.5);
    NSLog(@"SERIAL_SYNC_2");
});
dispatch_sync(q2, ^{
    sleep(2);
    NSLog(@"SERIAL_SYNC_3");
});


//3.3并行隊(duì)列異步執(zhí)行 輸出 2 1 4 3
dispatch_queue_t q3 = dispatch_queue_create("com.jr3", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(q3, ^{
    sleep(1);
    NSLog(@"CONCURRENT1");
});
dispatch_async(q3, ^{
    sleep(0.4);
    NSLog(@"CONCURRENT2");
});
dispatch_async(q3, ^{
    sleep(3);
    NSLog(@"CONCURRENT3");
});
dispatch_async(q3, ^{
    sleep(2);
    NSLog(@"CONCURRENT4");
});

//隊(duì)列組test1  同步任務(wù)1 同步任務(wù)超時(shí) 同步任務(wù)2 同步任務(wù)完成
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, globalQueue, ^{
    sleep(1);
    NSLog(@"同步任務(wù)1");
});
dispatch_group_async(group, globalQueue, ^{
    sleep(4);
    NSLog(@"同步任務(wù)2");
});
dispatch_group_notify(group, globalQueue, ^{
    NSLog(@"同步任務(wù)完成");
});
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);;
long result = dispatch_group_wait(group, time);
if (result == 0) {
    NSLog(@"任務(wù)全部執(zhí)行完畢");
}else{
    NSLog(@"同步任務(wù)超時(shí)");
}

//隊(duì)列組test2 異步任務(wù)2 異步任務(wù)1 任務(wù)結(jié)束
dispatch_group_t group2 = dispatch_group_create();
dispatch_queue_t groupQueue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group2, groupQueue2, ^{
    dispatch_group_enter(group2);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"異步任務(wù)1");
        dispatch_group_leave(group2);
    });
});
dispatch_group_async(group2, groupQueue2, ^{
    dispatch_group_enter(group2);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"異步任務(wù)2");
        dispatch_group_leave(group2);
    });
});
dispatch_group_notify(group2, groupQueue2, ^{
    NSLog(@"任務(wù)結(jié)束");
});
//異步的任務(wù)不能使用dispatch_group_wait,因?yàn)樵陂]包中的任務(wù)同步部分執(zhí)行完后任務(wù)就結(jié)束了班眯,但是dispatch_group_leave還沒有調(diào)用希停,所以一定返回任務(wù)沒有執(zhí)行成功
dispatch_time_t time2 = dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC);
long result2 = dispatch_group_wait(group2, time2);
if (result2==0) {
    NSLog(@"異步任務(wù)成功");
}else{
    NSLog(@"異步任務(wù)失敗");
}

//提交多個(gè)任務(wù) 可以實(shí)現(xiàn)對于數(shù)據(jù)的元素并發(fā)循環(huán)(dispatch_apply為同步返回,阻塞當(dāng)前線程直到所有的任務(wù)結(jié)束署隘,如果加入到串行隊(duì)列宠能,則所有的任務(wù)串行執(zhí)行,如果是并行隊(duì)列磁餐,則所有的任務(wù)并發(fā)執(zhí)行违崇。使用并行隊(duì)列,begin和end不一定成對,數(shù)字也不是按照順序輸出亦歉,如果使用串行隊(duì)列恤浪,begin和end成對輸出,并且數(shù)字按照順序輸出)
dispatch_queue_t applyQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t applyQueue2 = dispatch_queue_create("applyQueue", DISPATCH_QUEUE_SERIAL);
dispatch_apply(10, applyQueue2, ^(size_t index) {
    NSLog(@"indexBegin:%ld",index);
    sleep(0.3 * (10 - index));
    NSLog(@"%ld",index);
    NSLog(@"indexEnd:%ld",index);
});
NSLog(@"Apply done");

//隊(duì)列阻塞 (可解決讀者寫者的問題)
dispatch_queue_t dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(dbQueue, ^{
    NSLog(@"正在讀取1");
    sleep(1);
    NSLog(@"結(jié)束讀取1");
});
dispatch_async(dbQueue, ^{
    NSLog(@"正在讀取2");
    sleep(0.5);
    NSLog(@"結(jié)束讀取2");
});
dispatch_barrier_sync(dbQueue, ^{
    NSLog(@"正在寫入");
    sleep(5);
    NSLog(@"結(jié)束寫入");
});
dispatch_async(dbQueue, ^{
    NSLog(@"正在讀取3");
    sleep(0.5);
    NSLog(@"結(jié)束讀取3");
});

//隊(duì)列掛起與恢復(fù)
dispatch_queue_t someQueue = dispatch_queue_create("testQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_suspend(someQueue);
dispatch_resume(someQueue);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肴楷,一起剝皮案震驚了整個(gè)濱河市水由,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赛蔫,老刑警劉巖砂客,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異呵恢,居然都是意外死亡鞠值,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門渗钉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彤恶,“玉大人,你說我怎么就攤上這事鳄橘∩耄” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵瘫怜,是天一觀的道長术徊。 經(jīng)常有香客問我,道長鲸湃,這世上最難降的妖魔是什么赠涮? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮暗挑,結(jié)果婚禮上笋除,老公的妹妹穿的比我還像新娘。我一直安慰自己炸裆,他們只是感情好株憾,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晒衩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪墙歪。 梳的紋絲不亂的頭發(fā)上听系,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天,我揣著相機(jī)與錄音虹菲,去河邊找鬼靠胜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的浪漠。 我是一名探鬼主播陕习,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼名眉,長吁一口氣:“原來是場噩夢啊……” “哼吃挑!你這毒婦竟也來了从诲?” 一聲冷哼從身側(cè)響起饱须,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤蒙幻,失蹤者是張志新(化名)和其女友劉穎捌归,沒想到半個(gè)月后非区,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體亲茅,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡娘纷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年嫁审,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赖晶。...
    茶點(diǎn)故事閱讀 40,769評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡律适,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遏插,到底是詐尸還是另有隱情捂贿,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布涩堤,位于F島的核電站眷蜓,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏胎围。R本人自食惡果不足惜吁系,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望白魂。 院中可真熱鬧汽纤,春花似錦、人聲如沸福荸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽敬锐。三九已至背传,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間台夺,已是汗流浹背径玖。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留颤介,地道東北人梳星。 一個(gè)月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓赞赖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親冤灾。 傳聞我的和親對象是個(gè)殘疾皇子前域,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評論 2 361

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

  • 本篇博客共分以下幾個(gè)模塊來介紹GCD的相關(guān)內(nèi)容: 多線程相關(guān)概念 多線程編程技術(shù)的優(yōu)缺點(diǎn)比較? GCD中的三種隊(duì)列...
    有夢想的老伯伯閱讀 1,020評論 0 4
  • 歡迎大家指出文章中需要改正或者需要補(bǔ)充的地方韵吨,我會(huì)及時(shí)更新匿垄,非常感謝。 一. 多線程基礎(chǔ) 1. 進(jìn)程 進(jìn)程是指在系...
    xx_cc閱讀 7,197評論 11 70
  • .一.進(jìn)程 進(jìn)程:是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序,每個(gè)進(jìn)程之間是獨(dú)立的学赛,每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)存空...
    IIronMan閱讀 4,494評論 1 33
  • 一年堆、前言 上一篇文章iOS多線程淺匯-原理篇中整理了一些有關(guān)多線程的基本概念。本篇博文介紹的是iOS中常用的幾個(gè)多...
    nuclear閱讀 2,053評論 6 18
  • 多線程 在iOS開發(fā)中為提高程序的運(yùn)行效率會(huì)將比較耗時(shí)的操作放在子線程中執(zhí)行盏浇,iOS系統(tǒng)進(jìn)程默認(rèn)啟動(dòng)一個(gè)主線程变丧,用...
    郭豪豪閱讀 2,602評論 0 4