轉(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);