iOS多線程

轉(zhuǎn)載請注明出處:http://www.itdecent.cn/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ā)生??梢栽谀硹l線程和其他線程之間反復(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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本篇博客共分以下幾個(gè)模塊來介紹GCD的相關(guān)內(nèi)容: 多線程相關(guān)概念 多線程編程技術(shù)的優(yōu)缺點(diǎn)比較? GCD中的三種隊(duì)列...
    有夢想的老伯伯閱讀 1,087評論 0 4
  • 歡迎大家指出文章中需要改正或者需要補(bǔ)充的地方,我會(huì)及時(shí)更新,非常感謝。 一. 多線程基礎(chǔ) 1. 進(jìn)程 進(jìn)程是指在系...
    xx_cc閱讀 7,373評論 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,603評論 1 33
  • 一、前言 上一篇文章iOS多線程淺匯-原理篇中整理了一些有關(guān)多線程的基本概念。本篇博文介紹的是iOS中常用的幾個(gè)多...
    nuclear閱讀 2,141評論 6 18
  • 多線程 在iOS開發(fā)中為提高程序的運(yùn)行效率會(huì)將比較耗時(shí)的操作放在子線程中執(zhí)行,iOS系統(tǒng)進(jìn)程默認(rèn)啟動(dòng)一個(gè)主線程,用...
    郭豪豪閱讀 2,719評論 0 4

友情鏈接更多精彩內(nèi)容