
線程與多線程相關(guān)概念
進(jìn)程
- 資源分配的最小獨立單元,進(jìn)程是具有一定獨立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運行活動,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨立單位
線程
- 進(jìn)程下的一個分支,是進(jìn)程的實體,是CPU調(diào)度和分派的基本單元,它是比進(jìn)程更小的能獨立運行的基本單位,線程自己基本不擁有系統(tǒng)資源,只擁有一點在運行中必不可少的資源(程序計數(shù)器、一組寄存器、棧),但是它可與同屬一個進(jìn)程的其他線程共享進(jìn)程所擁有的全部資源。
進(jìn)程和線程的主要差別
- 在于它們是不同的操作系統(tǒng)資源管理方式。進(jìn)程有獨立的地址空間,一個進(jìn)程崩潰后,在保護(hù)模式下不會對其它進(jìn)程產(chǎn)生影響,而線程只是一個進(jìn)程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進(jìn)程死掉,所以多進(jìn)程的程序要比多線程的程序健壯,但在進(jìn)程切換時,耗費資源較大,效率要差一些。
重要概念(非常非常重要,不能理解這些概念多線程這輩子也學(xué)不會)
任務(wù):即操作,你想要干什么,說白了就是一段代碼,在 GCD 中就是一個 Block
隊列:用于存放任務(wù)
同步和異步:同步異步概念面向的是任務(wù)。同步指第一個任務(wù)不執(zhí)行完,不會開始第二個,異步是不管第一個有沒有執(zhí)行完,都開始第二個。
串行和并行:串行并行概念面向的是隊列。串行是多個任務(wù)按一定順序執(zhí)行,并行是多個任務(wù)同時執(zhí)行
iOS中隊列的種類有
- 串行隊列:隊列中的任務(wù)只會順序執(zhí)行
- 并行隊列: 隊列中的任務(wù)通常會并發(fā)執(zhí)行
- 主隊列:每一個應(yīng)用程序?qū)?yīng)唯一主隊列,直接GET即可;在多線程開發(fā)中,使用主隊列更新UI
- 全局隊列:是系統(tǒng)的,直接拿過來(GET)用就可以;與并行隊列類似
iOS中常用的多線程技術(shù)
pthread "已被拋棄"
NSThread
NSOperation
GCD
NSThread
NSThread是OC語言面向?qū)ο蟮亩嗑€程方案。所以你可以直接操控線程對象,非常直觀和方便。但是,它的生命周期還是需要我們手動管理,所以這套方案只有在一些非常簡單的場景才會用
創(chuàng)建并自動啟動
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:nil];```
- 獲取當(dāng)前線程
```swift
[NSThread currentThread];```
- 獲取主線程
```swift
[NSThread mainThread];```
----
####GCD
- GCD(Grand Central Dispatch)是基于C語言開發(fā)的一套多線程開發(fā)機(jī)制,也是目前蘋果官方推薦的多線程開發(fā)方法。它會自動合理地利用更多的CPU內(nèi)核(比如雙核、四核),最重要的是它會自動管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)、銷毀線程),完全不需要我們管理,我們只需要告訴干什么就行。
####隊列
- 獲取主隊列
dispatch_queue_t queue = dispatch_get_main_queue();```
- 獲取全局并行隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);```
----
####創(chuàng)建隊列
- 創(chuàng)建串行隊列
dispatch_queue_t queue = dispatch_queue_create("testQueue", NULL);```
- 創(chuàng)建并行隊列
dispatch_queue_t queue = dispatch_queue_create("testQueue", DISPATCH_QUEUE_CONCURRENT);```
####任務(wù)
- 創(chuàng)建同步任務(wù)
dispatch_sync(queue1, ^{
});```
- 創(chuàng)建異步任務(wù)
dispatch_async(queue2, ^{
});```
----
####隊列組
- 隊列組可以將很多隊列添加到一個組里,這樣做的好處是,當(dāng)這個組里所有的任務(wù)都執(zhí)行完了,隊列組會通過一個方法通知我們
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ù)
dispatch_group_async(group, queue, ^{
});
4、當(dāng)隊列組的方法全部執(zhí)行完后,會執(zhí)行
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
});```
線程死鎖
- 簡單的說,就是在當(dāng)前串行隊列中添加一個同步任務(wù),因為隊列是串行的只能一個一個的執(zhí)行任務(wù),而同步任務(wù)會阻塞隊列,這樣必須等該同步任務(wù)執(zhí)行完才能執(zhí)行其他任務(wù),但是該同步任務(wù)又是其他任務(wù)的一部分,所以兩個任務(wù)互相等待一直阻塞隊列,這就是線程死鎖。
NSOperation
NSOperation 是蘋果公司對 GCD 的封裝,完全面向?qū)ο螅允褂闷饋砀美斫狻?大家可以看到 NSOperation 和 NSOperationQueue 分別對應(yīng) GCD 的 任務(wù) 和 隊列 。
任務(wù)
NSOperation 只是一個抽象類,所以不能封裝任務(wù)。但它有 2 個子類用于封裝任務(wù)。分別是:NSInvocationOperation
和NSBlockOperation
。創(chuàng)建一個 Operation 后,需要調(diào)用 start 方法來啟動任務(wù),它會默認(rèn)在當(dāng)前隊列同步執(zhí)行。通過NSInvocationOperation創(chuàng)建任務(wù)
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];```
- 通過NSBlockOperation創(chuàng)建任務(wù)
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
}];```
- NSBlockOperation 還有一個方法:
addExecutionBlock:
,通過這個方法可以給 Operation 添加多個執(zhí)行Block
。
隊列
獲取主隊列
NSOperationQueue *queue = [NSOperationQueue mainQueue];
創(chuàng)建其他隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
往隊列中添加任務(wù)
[queue addOperation:operation];
NSOperationQueue有一個屬性maxConcurrentOperationCount代表最大并發(fā)數(shù),用來設(shè)置最多可以讓多少個任務(wù)同時執(zhí)行。當(dāng)設(shè)置為 1 的時候,就是串行隊列。```
----
####線程依賴
- NSOperation 有一個非常實用的功能,那就是添加依賴。比如有 3 個任務(wù):A: 從服務(wù)器上下載一張圖片,B:給這張圖片加個水印,C:把圖片返回給服務(wù)器。
- 這時就可以用到依賴了
[operation2 addDependency:operation1];
[operation3 addDependency:operation2];
[queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];```
- 返回主線程的方法
NSThread
[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:NO];
GCD
dispatch_async(dispatch_get_main_queue(), ^{
});```
####NSOperation
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
}];```
線程同步
所謂線程同步就是為了防止多個線程搶奪同一個資源造成的數(shù)據(jù)安全問題,所采取的一種措施。
互斥鎖 :給需要同步的代碼塊加一個互斥鎖,就可以保證每次只有一個線程訪問此代碼塊。
@synchronized(self) {
//需要執(zhí)行的代碼塊
}```
- 同步執(zhí)行 :我們可以把多個線程都要執(zhí)行此段代碼添加到同一個串行隊列,這樣就實現(xiàn)了線程同步的概念。