關(guān)于多線程編程首先我們要了解清楚什么是線程,什么是進(jìn)程,以及他們之間的區(qū)別和聯(lián)系。
所謂的線程就是CPU調(diào)度(執(zhí)行任務(wù))的最小單位,其實(shí)就是一段代碼。
而進(jìn)程是CPU分配資源和調(diào)度的單位,說(shuō)明白點(diǎn)就是系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序。
兩者的聯(lián)系和區(qū)別
線程是進(jìn)程的組成部分,一個(gè)進(jìn)程可以開(kāi)啟多個(gè)子線程,但是每一個(gè)進(jìn)程至少需要有一個(gè)線程;
一個(gè)進(jìn)程的所有任務(wù)都是在線程中執(zhí)行的
同一個(gè)進(jìn)程內(nèi)的線程共享進(jìn)程的資源
多線程的概念和原理
概念:一個(gè)程序開(kāi)啟多條線程,每條線程可以并行(同時(shí))執(zhí)行不同的任務(wù)
原理:(1)多個(gè)線程并發(fā)執(zhí)行,其本質(zhì)就是CPU快速地在多條線程之間切換。(2)當(dāng)CPU調(diào)度線程的時(shí)間足夠快,就會(huì)造成多線程并發(fā)執(zhí)行的假象。
那么了解了這么多,我們學(xué)習(xí)多線程開(kāi)發(fā)主要是為了什么呢?
簡(jiǎn)單來(lái)說(shuō)一下多線程的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):能適當(dāng)?shù)靥岣叱绦虻膱?zhí)行效率,能適當(dāng)提高資源利用率(CPU和內(nèi)存利用率)
缺點(diǎn):創(chuàng)建多線程是有開(kāi)銷的,包括內(nèi)存空間和創(chuàng)建時(shí)間上的開(kāi)銷,如果開(kāi)啟大量的線程,會(huì)導(dǎo)致程序性能降低,線程越多,CPU在調(diào)度線程上的開(kāi)銷就越大
到底什么是主線程,以及他有什么作用,下面讓我們一起探索一下
定義:iOS程序運(yùn)行后,默認(rèn)開(kāi)啟一條線程,稱為多線程
作用:顯示或刷新UI界面,處理UI事件
注意:不要將耗時(shí)操作放到主線程,耗時(shí)操作會(huì)卡死主線程,影響UI界面性能
實(shí)現(xiàn)多線程的方法主要有哪些?以及他們有哪些特點(diǎn)
NSThread:(偶爾OC)使用更加面向?qū)ο?簡(jiǎn)單易用,可直接操作線程對(duì)象
GCD:(經(jīng)常C)旨在替代NSThread等線程技術(shù),充分利用設(shè)備的多核
NSOperation:(經(jīng)常OC)基于GCD,比GCD多了一些更簡(jiǎn)單實(shí)用的功能,使用更加面向?qū)ο?/p>
項(xiàng)目中一般在哪用到多線程?
多線程一般用于耗時(shí)操作,如:網(wǎng)絡(luò)請(qǐng)求、上傳,下載文件、讀取數(shù)據(jù)庫(kù)、文件操作、大循環(huán)
什么是線程安全問(wèn)題?有什么解決方案?
定義:多個(gè)線程同時(shí)訪問(wèn)同一塊資源(例如同一個(gè)對(duì)象、變量、文件)時(shí),引發(fā)的數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全問(wèn)題,稱為線程安全問(wèn)題
解決方法:1.添加互斥鎖;2.互斥鎖的使用格式 :@synchronized( 鎖對(duì)象 ){ //需要鎖定的代碼};3.加鎖的原理:使線程同步執(zhí)行
FMDB是線程安全的么?
FMDB如果使用FMDatabase類是線程不安全的
使用FMDatabaseQueue是線程安全的
線程通信的概念,如何實(shí)現(xiàn)?
概念:一個(gè)線程傳遞數(shù)據(jù)給另一個(gè)線程、一個(gè)線程中執(zhí)行完特定任務(wù)后,轉(zhuǎn)到另一個(gè)線程繼續(xù)執(zhí)行任務(wù)
實(shí)現(xiàn)方法:
performSelectorOnMainThread和performSelectorOnThread方法
performSelectorInBackground(后臺(tái)線程中執(zhí)行)
使用GCD的dispatch方法
GCD內(nèi)部怎么實(shí)現(xiàn)的,使用GCD有什么優(yōu)勢(shì)?
實(shí)現(xiàn)方式:
1.通過(guò)定制任務(wù)和將任務(wù)添加到隊(duì)列中來(lái)實(shí)現(xiàn)GCD的多線程功能
2.GCD會(huì)自動(dòng)將隊(duì)列中的任務(wù)去出來(lái),放到對(duì)應(yīng)的線程中執(zhí)行
3.任務(wù)的取出遵循FIFO原則(先進(jìn)先出)
優(yōu)勢(shì):
1.會(huì)自動(dòng)利用更多的CPU內(nèi)核
2.會(huì)自動(dòng)管理線程的生命周期
全局并發(fā)隊(duì)列和使用create函數(shù)創(chuàng)建的并發(fā)隊(duì)列有什么區(qū)別?
1.全局并發(fā)隊(duì)列在整個(gè)程序中本身是默認(rèn)存在的,并且對(duì)應(yīng)有高優(yōu)先級(jí),默認(rèn)優(yōu)先級(jí),低優(yōu)先級(jí),后臺(tái)優(yōu)先級(jí)一共四種并發(fā)隊(duì)列,我們只是選擇其中一個(gè)來(lái)用,而使用create函數(shù)創(chuàng)建的并發(fā)隊(duì)列是實(shí)打?qū)嵉貜念^開(kāi)始去創(chuàng)建一個(gè)隊(duì)列
2.iOS6之前,使用create函數(shù)創(chuàng)建的隊(duì)列都要進(jìn)行一次Release,而全局并發(fā)隊(duì)列不需要我們手動(dòng)Release。但在iOS6之后,GCD已經(jīng)納入ARC內(nèi)存操作中,不需要再進(jìn)行Release
3.使用柵欄函數(shù)時(shí),使用全局并發(fā)隊(duì)列是無(wú)效的,只有使用create創(chuàng)建的并發(fā)隊(duì)列才有效(特別需要注意)
GCD中如何控制多線程并發(fā)執(zhí)行時(shí)的執(zhí)行順序
使用柵欄函數(shù)dispatch_barrier_async
GCD除了開(kāi)線程,還可以用在什么地方?
1.單例:一次函數(shù)dispatch_once
2.延遲函數(shù):dispatch_after,可以定義執(zhí)行任務(wù)的線程
3.定時(shí)器:dispatch_source_set_event_handler
4.快速迭代:dispatch_apply
GCD快速迭代的定義和作用?
定義:同時(shí)開(kāi)啟主線程和子線程并發(fā)完成循環(huán)操作
作用:大大提高循環(huán)操作的效率
GCD中隊(duì)列組的作用
使用隊(duì)列組,除了可以開(kāi)啟新的線程,同時(shí)還能通過(guò)group監(jiān)聽(tīng)隊(duì)列中任務(wù)的執(zhí)行情況
如何處理GCD造成的死鎖問(wèn)題
1.將隊(duì)列改為非主隊(duì)列
2.將調(diào)度方式改為異步調(diào)度
NSOperation和GCD的區(qū)別?
1.實(shí)現(xiàn)機(jī)制的區(qū)別:
(1).使用這兩者執(zhí)行任務(wù)都會(huì)由系統(tǒng)自動(dòng)創(chuàng)建、銷毀子線程
(2).GCD底層是基于C語(yǔ)言的,NSOperation則是對(duì)GCD的封裝,是面向?qū)ο蟮?/p>
(3).NSOperation只有兩種類型的隊(duì)列,主隊(duì)列和非主隊(duì)列(非主隊(duì)列既可以是并行的也可以是串行的,默認(rèn)是并行的)
(4).GCD擁有四種類型的隊(duì)列 (main, global, create[serial], create[concurrent] )
2.使用上的區(qū)別:
(1).GCD的使用更輕量級(jí),而NSOperation作為對(duì)象提供了更豐富的API
(2).在NSOperationQueue中,可以隨時(shí)取消要準(zhǔn)備執(zhí)行的任務(wù),而GCD沒(méi)法停止已經(jīng)加入queue的block中的任務(wù)
(3).KVO能應(yīng)用在NSOperation中,以監(jiān)聽(tīng)一個(gè)Operation是否完成或取消,這樣能比GCD更加有效地掌控我們執(zhí)行的后臺(tái)任務(wù)
(4).NSOperation通過(guò)繼承,可以提高代碼的復(fù)用度,這比GCD更有自由度和擴(kuò)展性
(5).同一個(gè)并行隊(duì)列中的任務(wù)執(zhí)行時(shí),我們能夠設(shè)置NSOperation的priority(優(yōu)先級(jí)),使之按順序執(zhí)行,而在GCD中,要使block中的任務(wù)實(shí)現(xiàn)這個(gè)功能,需要大量復(fù)雜代碼
什么是最大任務(wù)并發(fā)數(shù)?NSOperationQueue中如何操縱隊(duì)列中的任務(wù)?
線程的最大任務(wù)并發(fā)數(shù):異步執(zhí)行時(shí)同一時(shí)間內(nèi)可以同時(shí)執(zhí)行的操作的最大數(shù)
當(dāng)maxConcurrentOperationCount = 1,只能執(zhí)行一個(gè)操作,隊(duì)列為串行隊(duì)列
當(dāng)maxConcurrentOperationCount = 0,無(wú)法執(zhí)行任何操作
當(dāng)maxConcurrentOperationCount > 1,隊(duì)列為并發(fā)隊(duì)列
默認(rèn)條件下maxConcurrentOperationCount = -1,代表最大并發(fā)數(shù)沒(méi)有限制
NSOperationQueue處理A,B,C三個(gè)線程,要求執(zhí)行完A,B后才能執(zhí)行C,怎么做?
添加依賴關(guān)系,AB都依賴C
- (void)operation{
NSOperationQueue*queue = [[NSOperationQueuealloc] init];
NSBlockOperation*opA = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"A----%@",[NSThreadcurrentThread]);?
?}];
NSBlockOperation*opB = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"B----%@",[NSThreadcurrentThread]);
?}];
NSBlockOperation*opC = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"C----%@",[NSThreadcurrentThread]);
?}];
//注意:不能互相依賴
[opC addDependency:opA];
?[opC addDependency:opB];
?[queue addOperation:opA];?
?[queue addOperation:opB];
?[queue addOperation:opC];
NSLog(@"----end----");
}
有一個(gè)需求,需要將N個(gè)請(qǐng)求全部完成之后執(zhí)行某個(gè)操作,該如何處理
1.GCD中可以使用柵欄函數(shù)或者隊(duì)列組
2.NSOperation中可以添加依賴關(guān)系