06進階之路-多線程管理

1. GCD相關

學習鏈接

  1. GCD 簡介 (多核編程管理線程)
  2. GCD 任務和隊列(同步和異步任務 并發(fā)和串行隊列)
  3. GCD 的使用步驟
  4. GCD 的基本使用(6種不同組合區(qū)別)
區(qū)別 并發(fā)隊列 串行隊列 主隊列
同步(sync) 不開新線程,串行執(zhí)行 不開新線程,串行執(zhí)行 主線程:卡死 輔線程:回到主線程串行執(zhí)行
異步(async) 開線程,并發(fā)的執(zhí)行 開線程(1條),串行的執(zhí)行 沒有開線程,串行的執(zhí)行,一般用來回到主線程

同步主隊列線程卡死的原因:
主線程等待隊列任務完成,隊列任務同時等待主線程執(zhí)行


image
  1. GCD 線程間的通信(異步主隊類回主線程)
  2. GCD 的其他方法

柵欄方法:dispatch_barrier_async (并發(fā)隊列確保順序執(zhí)行)
重要的一個用法是實現(xiàn)多讀單寫

image

@interface UserCenter() {
    // 定義一個并發(fā)隊列
    dispatch_queue_t concurrent_queue;
    // 用戶數(shù)據(jù)中心, 可能多個線程需要數(shù)據(jù)訪問
    NSMutableDictionary *userCenterDic;
}
@end

// 多讀單寫模型
@implementation UserCenter

- (id)init {
    self = [super init];
    if (self) {
        // 通過宏定義 DISPATCH_QUEUE_CONCURRENT 創(chuàng)建一個并發(fā)隊列
        concurrent_queue = dispatch_queue_create("read_write_queue", DISPATCH_QUEUE_CONCURRENT);
        // 創(chuàng)建數(shù)據(jù)容器
        userCenterDic = [NSMutableDictionary dictionary];
    }
    return self;
}

- (id)objectForKey:(NSString *)key {
    __block id obj;
    // 同步讀取指定數(shù)據(jù)
    dispatch_sync(concurrent_queue, ^{
        obj = [userCenterDic objectForKey:key];
    });
    return obj;
}

- (void)setObject:(id)obj forKey:(NSString *)key {
    // 異步柵欄調用設置數(shù)據(jù)
    dispatch_barrier_async(concurrent_queue, ^{
        [userCenterDic setObject:obj forKey:key];
    });
}
@end
  • 延時執(zhí)行方法:dispatch_after(不一定精確,等主線程空閑才會開始執(zhí)行)

  • 一次性代碼(只執(zhí)行一次):dispatch_once(單例經常用到且是線程安全的)

  • 快速迭代方法:dispatch_apply
    通常我們會用 for 循環(huán)遍歷,但是 GCD 給我們提供了快速迭代的函數(shù) dispatch_apply。dispatch_apply 按照指定的次數(shù)將指定的任務追加到指定的隊列中,并等待全部隊列執(zhí)行結束。
    dispatch_apply 可以 在多個線程中同時(異步)遍歷多個數(shù)字。

  • 隊列組:dispatch_group(有幾種的工作使用方式)

(1)dispatch_group_notify
(2)dispatch_group_wait(暫停當前線程(阻塞當前線程),等待指定的 group 中的任務執(zhí)行完成后,才會往下繼續(xù)執(zhí)行)
(3)dispatch_group_enter、dispatch_group_leave
  • 信號量:dispatch_semaphore(線程安全和線程同步(為線程加鎖))

2. NSOperation相關

學習鏈接

  1. NSOperation、NSOperationQueue 簡介
    --是蘋果提供給我們的一套多線程解決方案。實際上 NSOperation、NSOperationQueue 是基于 GCD 更高一層的封裝,完全面向對象。但是比 GCD 更簡單易用、代碼可讀性也更高。
可添加完成的代碼塊,在操作完成后執(zhí)行。
添加操作之間的依賴關系,方便的控制執(zhí)行順序。
設定操作執(zhí)行的優(yōu)先級。
任務狀態(tài)的控制??梢院芊奖愕娜∠粋€操作的執(zhí)行。
使用 KVO 觀察對操作執(zhí)行狀態(tài)的更改:isExecuteing、isFinished、isCancelled。
設置最多并發(fā)數(shù)量
  1. 任務執(zhí)行狀態(tài)控制
  • isReady (當前任務是否就緒)
  • isExecuting (當前任務是否執(zhí)行中)
  • isFinished (當前任務是否完成)
  • isCancelled (當前任務是否取消)

控制方法:
如果只重寫main方法,底層控制變更任務執(zhí)行完成狀態(tài),以及任務退出。
如果重寫start方法,自行控制任務的狀態(tài)

  1. NSOperation、NSOperationQueue 使用步驟
創(chuàng)建操作:先將需要執(zhí)行的操作封裝到一個 NSOperation 對象中。
創(chuàng)建隊列:創(chuàng)建 NSOperationQueue 對象。
將操作加入到隊列中:將 NSOperation 對象添加到 NSOperationQueue 對象中。
  1. NSOperation 和 NSOperationQueue 基本使用
NSOperation 分為三類:NSInvocationOperation  NSBlockOperation 自定義繼承自 NSOperation 的子類

NSOperationQueue 一共有兩種隊列:主隊列(在主線程中)、自定義隊列。
  1. NSOperationQueue 控制串行執(zhí)行、并發(fā)執(zhí)行 (設置maxConcurrentOperationCount)

  2. NSOperation 操作依賴 (添加addDependency 移除removeDependency)

  3. NSOperation 優(yōu)先級 (queuePriority 決定開始順序,并不能替代依賴操作)

  4. NSOperation、NSOperationQueue 線程間的通信 ( [[NSOperationQueue mainQueue] addOperationWithBlock:^{.主線程UI操作.}];)

  5. NSOperation、NSOperationQueue 線程同步和線程安全

3. NSThread相關

  1. pthread

pthread 是一套通用的多線程的 API,可以在Unix / Linux / Windows 等系統(tǒng)跨平臺使用,使用 C 語言編寫,需要程序員自己管理線程的生命周期,使用難度較大,我們在 iOS 開發(fā)中幾乎不使用 pthread.

  1. NSThread

NSThread 是蘋果官方提供的,使用起來比 pthread 更加面向對象,簡單易用,可以直接操作線程對象。不過也需要需要程序員自己管理線程的生命周期(主要是創(chuàng)建),我們在開發(fā)的過程中偶爾使用 NSThread。比如我們會經常調用[NSThread currentThread]來顯示當前的進程信息。


image

常用方法

先創(chuàng)建線程,再啟動線程
// 1. 創(chuàng)建線程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
// 2. 啟動線程
[thread start];    // 線程一啟動,就會在線程thread中執(zhí)行self的run方法

創(chuàng)建線程后自動啟動線程
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];

隱式創(chuàng)建并啟動線程
// 1. 隱式創(chuàng)建并啟動線程
[self performSelectorInBackground:@selector(run) withObject:nil];

線程相關用法
// 獲得主線程
+ (NSThread *)mainThread;

// 判斷是否為主線程(對象方法)
- (BOOL)isMainThread;

// 判斷是否為主線程(類方法)
+ (BOOL)isMainThread;

// 獲得當前線程
NSThread *current = [NSThread currentThread];

// 線程的名字——setter方法
- (void)setName:(NSString *)n;

// 線程的名字——getter方法
- (NSString *)name;

線程狀態(tài)控制方法
啟動線程方法
- (void)start;
// 線程進入就緒狀態(tài) -> 運行狀態(tài)。當線程任務執(zhí)行完畢,自動進入死亡狀態(tài)

阻塞(暫停)線!程方法
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
// 線程進入阻塞狀態(tài)

強制停止線程
+ (void)exit;
// 線程進入死亡狀態(tài)

// 在主線程上執(zhí)行操作
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray<NSString *> *)array;
// equivalent to the first method with kCFRunLoopCommonModes

// 在指定線程上執(zhí)行操作
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array NS_AVAILABLE(10_5, 2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);

// 在當前線程上執(zhí)行操作,調用 NSObject 的 performSelector:相關方法
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

3.線程的狀態(tài)轉換

  • 如果CPU現(xiàn)在調度當前線程對象,則當前線程對象進入運行狀態(tài),如果CPU調度其他線程對象,則當前線程對象回到就緒狀態(tài)。
  • 如果CPU在運行當前線程對象的時候調用了sleep方法\等待同步鎖,則當前線程對象就進入了阻塞狀態(tài),等到sleep到時\得到同步鎖,則回到就緒狀態(tài)。
  • 如果CPU在運行當前線程對象的時候線程任務執(zhí)行完畢\異常強制退出,則當前線程對象進入死亡狀態(tài)。

image

4. 多線程與鎖

線程安全解決方案:可以給線程加鎖,在一個線程執(zhí)行該操作的時候,不允許其他線程進行操作。iOS 實現(xiàn)線程加鎖有很多種方式。
@synchronized、 NSLock、NSRecursiveLock、NSCondition、NSConditionLock、pthread_mutex、dispatch_semaphore、OSSpinLock、atomic(property) set/ge等等各種方式。

  • @synchronized 一般在創(chuàng)建單利對象的時候,保證線程安全
  • atomic 原子屬性,賦值是線程安全的,使用的時候不是
  • OSSpinLock 自旋鎖,循環(huán)等待詢問,忙等,適合輕量級操作(引用計數(shù)表使用的)
  • NSRecursiveLock 遞歸鎖。可以重入,遞歸調用的時候
  • NSLock 常用解決線程安全問題
  • dispatch_semaphore 計數(shù)性信號量,控制訪問數(shù)量
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容