關于多線程編程首先我們要了解清楚什么是線程玻靡,什么是進程,以及他們之間的區(qū)別和聯(lián)系歇盼。
所謂的線程就是CPU調(diào)度(執(zhí)行任務)的最小單位攘烛,其實就是一段代碼魏滚。
而進程是CPU分配資源和調(diào)度的單位,說明白點就是系統(tǒng)中正在運行的一個應用程序坟漱。
兩者的聯(lián)系和區(qū)別
線程是進程的組成部分鼠次,一個進程可以開啟多個子線程,但是每一個進程至少需要有一個線程靖秩;
一個進程的所有任務都是在線程中執(zhí)行的
同一個進程內(nèi)的線程共享進程的資源
多線程的概念和原理
概念:一個程序開啟多條線程须眷,每條線程可以并行(同時)執(zhí)行不同的任務
原理:(1)多個線程并發(fā)執(zhí)行,其本質(zhì)就是CPU快速地在多條線程之間切換沟突。(2)當CPU調(diào)度線程的時間足夠快,就會造成多線程并發(fā)執(zhí)行的假象捕传。
那么了解了這么多惠拭,我們學習多線程開發(fā)主要是為了什么呢?
簡單來說一下多線程的優(yōu)缺點
優(yōu)點:能適當?shù)靥岣叱绦虻膱?zhí)行效率庸论,能適當提高資源利用率(CPU和內(nèi)存利用率)
缺點:創(chuàng)建多線程是有開銷的职辅,包括內(nèi)存空間和創(chuàng)建時間上的開銷,如果開啟大量的線程聂示,會導致程序性能降低域携,線程越多,CPU在調(diào)度線程上的開銷就越大
到底什么是主線程鱼喉,以及他有什么作用秀鞭,下面讓我們一起探索一下
定義:iOS程序運行后趋观,默認開啟一條線程,稱為多線程
作用:顯示或刷新UI界面锋边,處理UI事件
注意:不要將耗時操作放到主線程皱坛,耗時操作會卡死主線程,影響UI界面性能
實現(xiàn)多線程的方法主要有哪些豆巨?以及他們有哪些特點
NSThread:(偶爾OC)使用更加面向?qū)ο?簡單易用剩辟,可直接操作線程對象
GCD:(經(jīng)常C)旨在替代NSThread等線程技術(shù),充分利用設備的多核
NSOperation:(經(jīng)常OC)基于GCD往扔,比GCD多了一些更簡單實用的功能贩猎,使用更加面向?qū)ο?/p>
項目中一般在哪用到多線程?
多線程一般用于耗時操作,如:網(wǎng)絡請求、上傳,下載文件萍膛、讀取數(shù)據(jù)庫吭服、文件操作、大循環(huán)
什么是線程安全問題卦羡?有什么解決方案噪馏?
定義:多個線程同時訪問同一塊資源(例如同一個對象、變量绿饵、文件)時欠肾,引發(fā)的數(shù)據(jù)錯亂和數(shù)據(jù)安全問題,稱為線程安全問題
解決方法:1.添加互斥鎖拟赊;2.互斥鎖的使用格式 :@synchronized( 鎖對象 ){ //需要鎖定的代碼}刺桃;3.加鎖的原理:使線程同步執(zhí)行
FMDB是線程安全的么?
FMDB如果使用FMDatabase類是線程不安全的
使用FMDatabaseQueue是線程安全的
線程通信的概念吸祟,如何實現(xiàn)瑟慈?
概念:一個線程傳遞數(shù)據(jù)給另一個線程、一個線程中執(zhí)行完特定任務后屋匕,轉(zhuǎn)到另一個線程繼續(xù)執(zhí)行任務
實現(xiàn)方法:
performSelectorOnMainThread和performSelectorOnThread方法
performSelectorInBackground(后臺線程中執(zhí)行)
使用GCD的dispatch方法
GCD內(nèi)部怎么實現(xiàn)的葛碧,使用GCD有什么優(yōu)勢?
實現(xiàn)方式:
1.通過定制任務和將任務添加到隊列中來實現(xiàn)GCD的多線程功能
2.GCD會自動將隊列中的任務去出來过吻,放到對應的線程中執(zhí)行
3.任務的取出遵循FIFO原則(先進先出)
優(yōu)勢:
1.會自動利用更多的CPU內(nèi)核
2.會自動管理線程的生命周期
全局并發(fā)隊列和使用create函數(shù)創(chuàng)建的并發(fā)隊列有什么區(qū)別进泼?
1.全局并發(fā)隊列在整個程序中本身是默認存在的,并且對應有高優(yōu)先級纤虽,默認優(yōu)先級乳绕,低優(yōu)先級,后臺優(yōu)先級一共四種并發(fā)隊列逼纸,我們只是選擇其中一個來用洋措,而使用create函數(shù)創(chuàng)建的并發(fā)隊列是實打?qū)嵉貜念^開始去創(chuàng)建一個隊列
2.iOS6之前,使用create函數(shù)創(chuàng)建的隊列都要進行一次Release杰刽,而全局并發(fā)隊列不需要我們手動Release菠发。但在iOS6之后王滤,GCD已經(jīng)納入ARC內(nèi)存操作中,不需要再進行Release
3.使用柵欄函數(shù)時雷酪,使用全局并發(fā)隊列是無效的淑仆,只有使用create創(chuàng)建的并發(fā)隊列才有效(特別需要注意)
GCD中如何控制多線程并發(fā)執(zhí)行時的執(zhí)行順序
使用柵欄函數(shù)dispatch_barrier_async
GCD除了開線程,還可以用在什么地方哥力?
1.單例:一次函數(shù)dispatch_once
2.延遲函數(shù):dispatch_after蔗怠,可以定義執(zhí)行任務的線程
3.定時器:dispatch_source_set_event_handler
4.快速迭代:dispatch_apply
GCD快速迭代的定義和作用?
定義:同時開啟主線程和子線程并發(fā)完成循環(huán)操作
作用:大大提高循環(huán)操作的效率
GCD中隊列組的作用
使用隊列組吩跋,除了可以開啟新的線程寞射,同時還能通過group監(jiān)聽隊列中任務的執(zhí)行情況
如何處理GCD造成的死鎖問題
1.將隊列改為非主隊列
2.將調(diào)度方式改為異步調(diào)度
NSOperation和GCD的區(qū)別?
1.實現(xiàn)機制的區(qū)別:
(1).使用這兩者執(zhí)行任務都會由系統(tǒng)自動創(chuàng)建锌钮、銷毀子線程
(2).GCD底層是基于C語言的桥温,NSOperation則是對GCD的封裝,是面向?qū)ο蟮?/p>
(3).NSOperation只有兩種類型的隊列,主隊列和非主隊列(非主隊列既可以是并行的也可以是串行的梁丘,默認是并行的)
(4).GCD擁有四種類型的隊列 (main, global, create[serial], create[concurrent] )
2.使用上的區(qū)別:
(1).GCD的使用更輕量級侵浸,而NSOperation作為對象提供了更豐富的API
(2).在NSOperationQueue中,可以隨時取消要準備執(zhí)行的任務氛谜,而GCD沒法停止已經(jīng)加入queue的block中的任務
(3).KVO能應用在NSOperation中掏觉,以監(jiān)聽一個Operation是否完成或取消,這樣能比GCD更加有效地掌控我們執(zhí)行的后臺任務
(4).NSOperation通過繼承值漫,可以提高代碼的復用度澳腹,這比GCD更有自由度和擴展性
(5).同一個并行隊列中的任務執(zhí)行時,我們能夠設置NSOperation的priority(優(yōu)先級)杨何,使之按順序執(zhí)行酱塔,而在GCD中,要使block中的任務實現(xiàn)這個功能危虱,需要大量復雜代碼
什么是最大任務并發(fā)數(shù)羊娃?NSOperationQueue中如何操縱隊列中的任務?
線程的最大任務并發(fā)數(shù):異步執(zhí)行時同一時間內(nèi)可以同時執(zhí)行的操作的最大數(shù)
當maxConcurrentOperationCount = 1埃跷,只能執(zhí)行一個操作迁沫,隊列為串行隊列
當maxConcurrentOperationCount = 0,無法執(zhí)行任何操作
當maxConcurrentOperationCount > 1捌蚊,隊列為并發(fā)隊列
默認條件下maxConcurrentOperationCount = -1,代表最大并發(fā)數(shù)沒有限制
NSOperationQueue處理A,B,C三個線程,要求執(zhí)行完A,B后才能執(zhí)行C,怎么做近弟?
添加依賴關系缅糟,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----");
}
有一個需求,需要將N個請求全部完成之后執(zhí)行某個操作祷愉,該如何處理
1.GCD中可以使用柵欄函數(shù)或者隊列組
2.NSOperation中可以添加依賴關系