簡介
對于許多面試題 會經(jīng)常問一些比較簡單問題 問線程 進(jìn)程區(qū)別 或者線程與隊列的到底有什么關(guān)系. 線程 和進(jìn)程關(guān)系這里就不講了比較簡單
線程與隊列的關(guān)系和區(qū)分
如圖 一個程序只有一個主隊列, 并且主隊列是一個特殊的串行隊列
所以說主隊列是一個串行隊列
綠圖(飯?zhí)媚P? 并行隊列 就是多條線程一起 執(zhí)行任務(wù)沒有順序
如果把這個圖看成一個進(jìn)程的話 那么這個進(jìn)程里一共開了四條線程.(一個主線程 三個子線程).
如何開線程
在ios里面一共有三種方式 開辟線程 1.NSThread 2.GCD 3.NSOPeration
第一種很少人會用 他是oc開線程的方法 因為有許多缺點 所以很少人會用(缺點:手動管理線程, 無法利用多核技術(shù))
第二種 第三種 需要掌握 這里我們主要說說GCD 是如何開線程的
第三種NSOPeration 是對蘋果公司 對GCD 的一個封裝(掌握)
GCD 應(yīng)用廣泛
自動開線程 ,延遲操作,運用于單例的創(chuàng)建等.
GCD開線程
大家都聽過異步 和同步吧 其實異步和同步 就是用GCD 來寫的
大家記住一件事
dispatch_async(dispatch_get_main_queue(), ^{ });異步里參數(shù)除非是dispatch_get_main_queue() 這個主隊列 其余的包括 全局隊列(并行隊列) 和串行隊列放入這個異步 作為參數(shù)時 他們都會自動創(chuàng)建線程
那么在異步添加到 并行隊列(全局隊列)與串行隊列 都會自動開線程那么他們有什么區(qū)別嗎?
全局隊列是什么 他是一個系統(tǒng)自帶的并行隊列 所以大家以后不用創(chuàng)建并行隊列 直接用.
串行隊列 需要手動創(chuàng)建 程序里 已經(jīng)有了一個特殊的串行隊列dispatch_get_main_queue()(主隊列)主隊列比較特殊 異步加入主線程 這個異步不會開啟線程 . 會在主線程執(zhí)行
但是自定義創(chuàng)建的串行隊列 就不一樣了
/**
* async -- 并發(fā)隊列(最常用)
* 會不會創(chuàng)建線程:會奇适,一般同時開多條
* 任務(wù)的執(zhí)行方式:并發(fā)執(zhí)行
*/
- (void)asyncGlobalQueue
{
// 獲得全局的并發(fā)隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 將 任務(wù) 添加 全局隊列 中去 異步 執(zhí)行
dispatch_async(queue, ^{
NSLog(@"-----下載圖片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片2---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片3---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片4---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片5---%@", [NSThread currentThread]);
});
}
/**
* async -- 串行隊列(有時候用)
* 會不會創(chuàng)建線程:會,一般只開1條線程
* 任務(wù)的執(zhí)行方式:串行執(zhí)行(一個任務(wù)執(zhí)行完畢后再執(zhí)行下一個任務(wù))
*/
- (void)asyncSerialQueue
{
// 1.創(chuàng)建一個串行隊列
dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL);
// 2.將任務(wù)添加到串行隊列中 異步 執(zhí)行
dispatch_async(queue, ^{
NSLog(@"-----下載圖片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片2---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片3---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片4---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下載圖片5---%@", [NSThread currentThread]);
});
把這幾行代碼粘到你工程中 你就明白了(打印當(dāng)前線程) 如代碼注釋所示 異步加入串行隊列 無論你寫多少異步 加入者個串行隊列 他只會開一條線程.
而異步加入全局隊列 你有幾個異步那么他開幾個線程(最好不要超過5個).
線程的鎖死
簡單的鎖死 有些人 會在主線程中 執(zhí)行dispatch_sync(dispatch_get_main_queue(), ^{ });
這一行的代碼 這樣會造成鎖死
原因
寫了這句話他會加入主線程隊列里 等待主線程完成 才回返回block里面的內(nèi)容.但是當(dāng)程序運行到這行代碼 由于主線程沒有完成 block 不會有返回.并且也不會跳過這行代碼 所以就造成了死鎖現(xiàn)象.
主隊列和主線程的區(qū)別
代碼描述[NSOperationQueue mainQueue]主隊列 [NSThread mainThread]主線程
二者關(guān)系 主隊列里 必須有一個主線程 主隊列里可以在加線程
同步加入全局隊列要注意的是
dispatch_sync 在全局隊列是可以寫的 等主隊列執(zhí)行完了 它再執(zhí)行就是了 沒什么大不了