iOS 多線程開發(fā)--GCD

GCD

Grand Central Dispatch,是蘋果為多核的并行運算提出的解決方案胁勺,所以會自動合理地利用更多的CPU內(nèi)核(比如雙核怀愧、四核),最重要的是它會自動管理線程的生命周期(創(chuàng)建線程挫酿、調(diào)度任務(wù)构眯、銷毀線程),完全不需要我們管理早龟,我們只需要告訴干什么就行惫霸。同時它使用的也是 c語言,不過由于使用了 BlockSwift里叫做閉包)葱弟,使得使用起來更加方便壹店,而且靈活。所以基本上大家都使用GCD這套方案芝加。

任務(wù)和隊列

GCD中硅卢,加入了兩個非常重要的概念: 任務(wù)隊列

  • 任務(wù):即操作藏杖,你想要干什么将塑,說白了就是一段代碼,在 GCD 中就是一個Block蝌麸,所以添加任務(wù)十分方便点寥。任務(wù)有兩種執(zhí)行方式:** 同步執(zhí)行 **和 異步執(zhí)行,他們之間的區(qū)別是 是否會創(chuàng)建新的線程来吩。
    同步(sync)異步(async) 的主要區(qū)別在于會不會阻塞當前線程敢辩,直到 Block中的任務(wù)執(zhí)行完畢!
    如果是同步(sync) 操作弟疆,它會阻塞當前線程并等待Block 中的任務(wù)執(zhí)行完畢戚长,然后當前線程才會繼續(xù)往下運行。
    如果是 異步(async)操作怠苔,當前線程會直接往下執(zhí)行同廉,它不會阻塞當前線程。

  • 隊列:用于存放任務(wù)嘀略。一共有兩種隊列恤溶, 串行隊列并行隊列
    串行隊列 中的任務(wù)會根據(jù)隊列的定義 FIFO 的執(zhí)行帜羊,一個接一個的先進先出的進行執(zhí)行咒程。
    并行隊列 放到并行隊列的任務(wù),GCD 也會 FIFO的取出來讼育,但不同的是帐姻,它取出來一個就會放到別的線程稠集,然后再取出來一個又放到另一個的線程。這樣由于取的動作很快饥瓷,忽略不計剥纷,看起來,所有的任務(wù)都是一起執(zhí)行的呢铆。不過需要注意晦鞋,GCD 會根據(jù)系統(tǒng)資源控制并行的數(shù)量,所以如果任務(wù)很多棺克,它并不會讓所有任務(wù)同時執(zhí)行悠垛。

創(chuàng)建隊列

  • 主隊列:這是一個特殊的 串行隊列蒙畴。什么是主隊列邢锯,大家都知道吧,它用于刷新 UI候生,任何需要刷新 UI 的工作都要在主隊列執(zhí)行纱皆,所以一般耗時的任務(wù)都要放到別的線程執(zhí)行湾趾。
//OBJECTIVE-C 
dispatch_queue_t queue = dispatch_get_main_queue(); 
//SWIFT 
let queue = dispatch_get_main_queue()
  • 自己創(chuàng)建的隊列:自己可以創(chuàng)建 串行隊列, 也可以創(chuàng)建 并行隊列。 看下面的代碼派草,它有兩個參數(shù)搀缠,其中第一個參數(shù)是標識符,用于 DEBUG的時候標識唯一的隊列澳眷,可以為空胡嘿。大家可以看xcode的文檔查看參數(shù)意義,第二個才是最重要的钳踊。
    第二個參數(shù)用來表示創(chuàng)建的隊列是串行的還是并行的,傳入 DISPATCH_QUEUE_SERIALNULL 表示創(chuàng)建串行隊列勿侯。傳入 DISPATCH_QUEUE_CONCURRENT 表示創(chuàng)建并行隊列拓瞪。
//OBJECTIVE-C
//串行隊列 
dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", NULL); 
dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", 
DISPATCH_QUEUE_SERIAL); 
//并行隊列 
dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_CONCURRENT); 
//SWIFT
 //串行隊列 
let queue = dispatch_queue_create("tk.bourne.testQueue", nil); 
let queue = dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_SERIAL) 
//并行隊列 
let queue = dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_CONCURRENT)
  • 全局并行隊列:只要是并行任務(wù)一般都加入到這個隊列。這是系統(tǒng)提供的一個并發(fā)隊列助琐。
  //OBJECTIVE-C
  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

  //SWIFT
  let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

創(chuàng)建任務(wù)

  • 同步任務(wù):會阻塞當前線程 (SYNC)
    OBJECTIVE-C
  dispatch_sync(<#queue#>, ^{
      //code here
      NSLog(@"%@", [NSThread currentThread]);
  });

SWIFT

  dispatch_sync(<#queue#>, { () -> Void in
      //code here
      println(NSThread.currentThread())
  })
  • 異步任務(wù):不會阻塞當前線程 (ASYNC)
    OBJECTIVE-C
  dispatch_async(<#queue#>, ^{
      //code here
      NSLog(@"%@", [NSThread currentThread]);
  });

SWIFT

  dispatch_async(<#queue#>, { () -> Void in
      //code here
      println(NSThread.currentThread())
  })

隊列組

隊列組可以將很多隊列添加到一個組里祭埂,這樣做的好處是,當這個組里所有的任務(wù)都執(zhí)行完了兵钮,隊列組會通過一個方法通知我們蛆橡。下面是使用方法,這是一個很實用的功能掘譬。

OBJECTIVE-C

//1.創(chuàng)建隊列組
dispatch_group_t group = dispatch_group_create();
//2.創(chuàng)建隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//3.多次使用隊列組的方法執(zhí)行任務(wù), 只有異步方法
//3.1.執(zhí)行3次循環(huán)
dispatch_group_async(group, queue, ^{
    for (NSInteger i = 0; i < 3; i++) {
        NSLog(@"group-01 - %@", [NSThread currentThread]);
    }
});

//3.2.主隊列執(zhí)行8次循環(huán)
dispatch_group_async(group, dispatch_get_main_queue(), ^{
    for (NSInteger i = 0; i < 8; i++) {
        NSLog(@"group-02 - %@", [NSThread currentThread]);
    }
});

//3.3.執(zhí)行5次循環(huán)
dispatch_group_async(group, queue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"group-03 - %@", [NSThread currentThread]);
    }
});

//4.都完成后會自動通知
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    NSLog(@"完成 - %@", [NSThread currentThread]);
});

SWIFT

//1.創(chuàng)建隊列組
let group = dispatch_group_create()
//2.創(chuàng)建隊列
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

//3.多次使用隊列組的方法執(zhí)行任務(wù), 只有異步方法
//3.1.執(zhí)行3次循環(huán)
dispatch_group_async(group, queue) { () -> Void in
    for _ in 0..<3 {
        NSLog("group-01 - %@", NSThread.currentThread())
    }
}

//3.2.主隊列執(zhí)行8次循環(huán)
dispatch_group_async(group, dispatch_get_main_queue()) { () -> Void in
    for _ in 0..<8 {
        NSLog("group-02 - %@", NSThread.currentThread())
    }
}

//3.3.執(zhí)行5次循環(huán)
dispatch_group_async(group, queue) { () -> Void in
    for _ in 0..<5 {
        NSLog("group-03 - %@", NSThread.currentThread())
    }
}

//4.都完成后會自動通知
dispatch_group_notify(group, dispatch_get_main_queue()) { () -> Void in
    NSLog("完成 - %@", NSThread.currentThread())
}

打印結(jié)果

2017-04-10 03:40:34.277 test[12540:3319271] group-03 - <NSThread: 0x7f9772536f00>{number = 3, name = (null)}
2017-04-10 03:40:34.277 test[12540:3319146] group-02 - <NSThread: 0x7f977240ba60>{number = 1, name = main}
2017-04-10 03:40:34.277 test[12540:3319146] group-02 - <NSThread: 0x7f977240ba60>{number = 1, name = main}
2017-04-10 03:40:34.277 test[12540:3319271] group-03 - <NSThread: 0x7f9772536f00>{number = 3, name = (null)}
2017-04-10 03:40:34.278 test[12540:3319146] group-02 - <NSThread: 0x7f977240ba60>{number = 1, name = main}
2017-04-10 03:40:34.278 test[12540:3319271] group-03 - <NSThread: 0x7f9772536f00>{number = 3, name = (null)}
2017-04-10 03:40:34.278 test[12540:3319271] group-03 - <NSThread: 0x7f9772536f00>{number = 3, name = (null)}
2017-04-10 03:40:34.278 test[12540:3319146] group-02 - <NSThread: 0x7f977240ba60>{number = 1, name = main}
2017-04-10 03:40:34.277 test[12540:3319273] group-01 - <NSThread: 0x7f977272e8d0>{number = 2, name = (null)}
2017-04-10 03:40:34.278 test[12540:3319271] group-03 - <NSThread: 0x7f9772536f00>{number = 3, name = (null)}
2017-04-10 03:40:34.278 test[12540:3319146] group-02 - <NSThread: 0x7f977240ba60>{number = 1, name = main}
2017-04-10 03:40:34.278 test[12540:3319273] group-01 - <NSThread: 0x7f977272e8d0>{number = 2, name = (null)}
2017-04-10 03:40:34.278 test[12540:3319146] group-02 - <NSThread: 0x7f977240ba60>{number = 1, name = main}
2017-04-10 03:40:34.278 test[12540:3319273] group-01 - <NSThread: 0x7f977272e8d0>{number = 2, name = (null)}
2017-04-10 03:40:34.279 test[12540:3319146] group-02 - <NSThread: 0x7f977240ba60>{number = 1, name = main}
2017-04-10 03:40:34.279 test[12540:3319146] group-02 - <NSThread: 0x7f977240ba60>{number = 1, name = main}
2017-04-10 03:40:34.279 test[12540:3319146] 完成 - <NSThread: 0x7f977240ba60>{number = 1, name = main}

這些就是 GCD 的基本功能,只要你想象力夠豐富泰演,你可以組合出更好的用法。

補充

  1. func dispatch_barrier_async(_ queue: dispatch_queue_t, _ block: dispatch_block_t):
    這個方法重點是你傳入的queue葱轩,當你傳入的 queue 是通過 DISPATCH_QUEUE_CONCURRENT 參數(shù)自己創(chuàng)建的 queue 時睦焕,這個方法會阻塞這個 queue(注意是阻塞 queue 藐握,而不是阻塞當前線程),一直等到這個 queue 中排在它前面的任務(wù)都執(zhí)行完成后才會開始執(zhí)行自己垃喊,自己執(zhí)行完畢后猾普,才會取消阻塞,使這個 queue 中排在它后面的任務(wù)繼續(xù)執(zhí)行本谜。
    如果你傳入的是其他的 queue, 那么它就和 dispatch_async 一樣了初家。

  2. func dispatch_barrier_sync(_ queue: dispatch_queue_t, _ block: dispatch_block_t):
    這個方法的使用和上一個一樣,傳入 自定義的并發(fā)隊列(DISPATCH_QUEUE_CONCURRENT)乌助,它和上一個方法一樣的阻塞 queue笤成,不同的是 這個方法還會 阻塞當前線程。
    如果你傳入的是其他的 queue, 那么它就和 dispatch_sync 一樣了眷茁。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炕泳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子上祈,更是在濱河造成了極大的恐慌培遵,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件登刺,死亡現(xiàn)場離奇詭異籽腕,居然都是意外死亡,警方通過查閱死者的電腦和手機纸俭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門皇耗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人揍很,你說我怎么就攤上這事郎楼。” “怎么了窒悔?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵呜袁,是天一觀的道長。 經(jīng)常有香客問我简珠,道長阶界,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任聋庵,我火速辦了婚禮膘融,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘祭玉。我一直安慰自己氧映,他們只是感情好,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布攘宙。 她就那樣靜靜地躺著屯耸,像睡著了一般拐迁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上疗绣,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天线召,我揣著相機與錄音,去河邊找鬼多矮。 笑死缓淹,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的塔逃。 我是一名探鬼主播讯壶,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼湾盗!你這毒婦竟也來了伏蚊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤格粪,失蹤者是張志新(化名)和其女友劉穎躏吊,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帐萎,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡比伏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了疆导。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赁项。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖澈段,靈堂內(nèi)的尸體忽然破棺而出悠菜,到底是詐尸還是另有隱情,我是刑警寧澤均蜜,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布李剖,位于F島的核電站,受9級特大地震影響囤耳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜偶芍,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一充择、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧匪蟀,春花似錦椎麦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琴儿。三九已至,卻和暖如春嘁捷,著一層夾襖步出監(jiān)牢的瞬間造成,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工雄嚣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留晒屎,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓缓升,卻偏偏與公主長得像鼓鲁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子港谊,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

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