1.dispatch_async和dispatch_sync的區(qū)別
(來自http://www.cnblogs.com/zhidao-chen/p/3598215.html?的總結(jié))
首先,同锄开、異步操作只是在當(dāng)前線程中彩扔,操作的是否按照順序執(zhí)行的問題,與線程無必然聯(lián)系蒸痹。
主線程中可以有同步春弥,異步操作,子線程里也可以有同步和異步的操作叠荠。
只是如果執(zhí)行異步操作了匿沛,說明在當(dāng)前線程中(可能當(dāng)前是主線程或一個子線程),必然啟動了一個子線程來執(zhí)行任務(wù)榛鼎,異步操作也叫做“把一個操作放進(jìn)了一個非主隊(duì)列的隊(duì)列中執(zhí)行”逃呼。
dispatch_sync(),同步添加操作(進(jìn)隊(duì)列中)鳖孤。他是等待添加進(jìn)隊(duì)列里面的操作完成之后再繼續(xù)執(zhí)行。
dispatch_async ,異步添加進(jìn)任務(wù)隊(duì)列抡笼,它不會做任何等待苏揣。
dispatch_async(queue,block) async 異步隊(duì)列,dispatch_async函數(shù)會立即返回, block會在后臺異步執(zhí)行推姻。
dispatch_sync(queue,block) sync 同步隊(duì)列平匈,dispatch_sync函數(shù)不會立即返回,即阻塞當(dāng)前線程,等待 block同步執(zhí)行完成藏古。
總結(jié):
首先區(qū)分異步和同步操作:
dispatch_sync(),同步添加操作吐葱。它是等待添加進(jìn)()里面的操作完成之后再繼續(xù)執(zhí)行。
dispatch_async ,異步添加進(jìn)任務(wù)隊(duì)列校翔,它不會做任何等待弟跑,跳過執(zhí)行之后的代碼去。
然后是區(qū)分串行隊(duì)列和并行隊(duì)列:
串行隊(duì)列:添加進(jìn)隊(duì)列的任務(wù)順序執(zhí)行
并行隊(duì)列:添加進(jìn)隊(duì)列的任務(wù)并行執(zhí)行防症,順序不一定
另外孟辑,主隊(duì)列是特殊的串行隊(duì)列,全局隊(duì)列dispatch_get_global_queue是系統(tǒng)自帶并發(fā)隊(duì)列蔫敲,可以直接使用饲嗽。隊(duì)列能代表著線程,主隊(duì)列執(zhí)行任務(wù)就是在主線程里執(zhí)行任務(wù)奈嘿,非主隊(duì)列執(zhí)行任務(wù)就是在子隊(duì)列執(zhí)行任務(wù)貌虾。
但注意,只有將dispatch_async(代表異步)搭配非主隊(duì)列(代表并發(fā))執(zhí)行任務(wù)裙犹,才叫做多線程操作尽狠。多線程肯定應(yīng)該是異步并發(fā)執(zhí)行。
注意:異步叶圃、隊(duì)列袄膏、線程的關(guān)系:http://www.reibang.com/p/8e81d8caee34
隊(duì)列中可以添加多個線程,多個線程可以在這串行(hang)隊(duì)列里一次執(zhí)行一個線程掺冠;或者在并發(fā)隊(duì)列里沉馆,一次執(zhí)行多個線程。
!!!! 通過dispatch_async 使用異步德崭,來將任務(wù)添加到隊(duì)列中斥黑,會創(chuàng)建線程來執(zhí)行任務(wù),從而實(shí)現(xiàn)了異步操作眉厨,多線程操作锌奴。
并行隊(duì)列 就是多條線程一起 執(zhí)行任務(wù)
1.dispatch_sync:同步添加任務(wù)到隊(duì)列,不會創(chuàng)建新的線程缺猛,都是在當(dāng)前線程中處理的缨叫。無論添加到串行隊(duì)列里或者并行隊(duì)列里,都是串行效果荔燎,因?yàn)檫@個方法是等任務(wù)執(zhí)行完成以后才會返回耻姥。
2.dispatch_async:異步添加任務(wù)到
2-1:mainQueue不創(chuàng)建線程,在主線程中串行執(zhí)行
2-2:globalQueue 和 并行隊(duì)列:根據(jù)任務(wù)系統(tǒng)決定開辟線程個數(shù)
2-3:串行對列:創(chuàng)建一個線程:串行執(zhí)行有咨。
異步是用來加入到隊(duì)列中琐簇,這樣會開辟線程來執(zhí)行操作。
且無論多少個異步加入到串行隊(duì)列座享,都只會開一個線程婉商;有多少個異步加入到并行隊(duì)列,就會開辟多少個線程渣叛。
所以啟動多線程里執(zhí)行的是一個blcok語句塊丈秩,這樣就是在異步執(zhí)行block里的內(nèi)容,寫法很方便簡潔淳衙。
2.關(guān)于全局隊(duì)列和并發(fā)隊(duì)列
dispatch_queue_create(nil,DISPATCH_QUEUE_CONCURRENT);是創(chuàng)建了一個并發(fā)隊(duì)列蘑秽,屬于自定義的用戶隊(duì)列
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);也是一個并發(fā)隊(duì)列,屬于一個全局的并發(fā)隊(duì)列箫攀;
3.GCD Queue 分為三種:
http://www.reibang.com/p/46500f070e9c
1肠牲,The main queue :主隊(duì)列(主線程的串行隊(duì)列),主線程就是在個隊(duì)列中靴跛。
2缀雳,Global queues : 全局(并發(fā))隊(duì)列。
3梢睛,用戶(自定義)隊(duì)列:是用函數(shù)dispatch_queue_create創(chuàng)建的自定義隊(duì)列肥印。可以創(chuàng)建 并發(fā)隊(duì)列和串行隊(duì)列绝葡。
注意:
并發(fā)隊(duì)列竖独,用于實(shí)現(xiàn)隊(duì)列們之間同時(shí)并發(fā)地執(zhí)行。如果你的需求需要某個并發(fā)線程先執(zhí)行挤牛,可以通過設(shè)置優(yōu)先級來達(dá)到目的莹痢,但是因?yàn)榫€程是并發(fā)執(zhí)行的,所以你不能保證哪個線程會先執(zhí)行完墓赴,也就是不能保證我們的耗時(shí)任務(wù)是按照順序執(zhí)行的竞膳。
串行隊(duì)列,用于實(shí)現(xiàn)隊(duì)列間順序執(zhí)行诫硕。
4.GCDDelay:延遲執(zhí)行: ?需求延遲3秒后坦辟,執(zhí)行某項(xiàng)操作
與NSThread的延遲執(zhí)行比較:NSThread冗長,但精確度高章办,且能取消延遲執(zhí)行操作锉走;GCDDelay代碼精簡滨彻,但有毫秒級誤差,沒有取消操作挪蹭。
dispatch_queue_tconcurrentQueue =dispatch_queue_create("my.concurrent.queue",DISPATCH_QUEUE_CONCURRENT);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,NSEC_PER_SEC*2.f), concurrentQueue, ^{
NSLog(@"GCD延遲2秒執(zhí)行");
});
5.GCDGroup:能夠監(jiān)聽 加入到組中的線程的執(zhí)行情況亭饵。從而可以實(shí)現(xiàn)一些特殊需要,如既希望多線程間并發(fā)執(zhí)行梁厉,又希望其中一個線程在其他線程完成后執(zhí)行辜羊。
使用:
1、創(chuàng)建線程組:dispatch_group_tgroup =dispatch_group_create();
2词顾、創(chuàng)建一個線程隊(duì)列dispatch_queue_tqueue =dispatch_queue_create("my.concurrent.queue",DISPATCH_QUEUE_CONCURRENT);
3八秃、讓隊(duì)列中的每一個線程,都在group中運(yùn)行
dispatch_group_async(group, queue, ^{
NSLog(@"1");
});
4肉盹、notify監(jiān)聽線程組中 之前的線程是否執(zhí)行完成昔驱,并執(zhí)行block
dispatch_group_notify(group, queue, ^{
NSLog(@"3");
});
6.GCDTimer:GCD定時(shí)器,讓一個操作在GCD定時(shí)器開啟后上忍,在某線程內(nèi)舍悯,每個NSEC_PER_SEC時(shí)間執(zhí)行一次。
//獲得隊(duì)列
dispatch_queue_tqueue =dispatch_get_main_queue();
//創(chuàng)建一個定時(shí)器(dispatch_source_t本質(zhì)還是個OC對象)
dispatch_source_ttimer =dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0, queue);
//設(shè)置定時(shí)器的各種屬性(幾時(shí)開始任務(wù)睡雇,每隔多長時(shí)間執(zhí)行一次)
// GCD的時(shí)間參數(shù)萌衬,一般是納秒NSEC_PER_SEC(1秒== 10的9次方納秒)
//何時(shí)開始執(zhí)行第一個任務(wù)
// dispatch_time(DISPATCH_TIME_NOW, 3.0 * NSEC_PER_SEC)比當(dāng)前時(shí)間晚3秒
dispatch_time_tstart =dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0*NSEC_PER_SEC));
uint64_tinterval = (uint64_t)(1.0*NSEC_PER_SEC);
dispatch_source_set_timer(timer, start, interval,0);
//設(shè)置回調(diào)
dispatch_source_set_event_handler(timer, ^{
NSLog(@"GCD定時(shí)器");
});
//啟動定時(shí)器
dispatch_resume(timer);
7.GCDSemaphore:信號量,能實(shí)現(xiàn)讓兩個異步線程它抱,同步執(zhí)行秕豫。
使用方法:先創(chuàng)建GCDSemaphore,然后在需要先執(zhí)行的線程中 讓發(fā)出信號观蓄,再在需要后執(zhí)行的線程中 讓信號等待混移。
//信號量的使用就這3句
// 1.創(chuàng)建信號量
dispatch_semaphore_tdispatchSemaphore =dispatch_semaphore_create(0);
dispatch_queue_tgQueue =dispatch_get_global_queue(0,0);
dispatch_async(gQueue, ^{
NSLog(@"1");
//??????? 2.發(fā)送信號量
dispatch_semaphore_signal(dispatchSemaphore);//線程1執(zhí)行完進(jìn)行發(fā)送信號
});
dispatch_async(gQueue, ^{
//??????? 3.等待信號(發(fā)送與等待信號量是配對使用的)
//原理:線程1,2會同時(shí)并發(fā)的執(zhí)行侮穿,到線程2執(zhí)行到這里歌径,遇到dispatch_semaphore_wait,會停下來看看是否信號量已發(fā)送亲茅,發(fā)送了才往下執(zhí)行
dispatch_semaphore_wait(dispatchSemaphore,DISPATCH_TIME_FOREVER);//線程2的內(nèi)容執(zhí)行前等待信號
NSLog(@"2");
});