多線程編程

1.術(shù)語(yǔ)
線程:用于指代獨(dú)立執(zhí)行的代碼段
進(jìn)程:用于指代一個(gè)正在運(yùn)行的可執(zhí)行程序,它可以包含多個(gè)線程。
任務(wù):用于指代抽象的概念,表示需要執(zhí)行工作。

兩個(gè)通用隊(duì)列:
串行隊(duì)列:所有任務(wù)會(huì)在一條線程中執(zhí)行(有可能是當(dāng)前線程也有可能是新開(kāi)辟的線程),并且一個(gè)任務(wù)執(zhí)行完畢后,才開(kāi)始執(zhí)行下一個(gè)任務(wù)。(等待完成)

并行隊(duì)列:可以開(kāi)啟多條線程并行執(zhí)行任務(wù)(但不一定會(huì)開(kāi)啟新的線程),并且當(dāng)一個(gè)任務(wù)放到指定線程開(kāi)始執(zhí)行時(shí),下一個(gè)任務(wù)就可以開(kāi)始執(zhí)行了。(等待發(fā)生)
兩個(gè)特殊隊(duì)列:

主隊(duì)列:系統(tǒng)為我們創(chuàng)建好的一個(gè)串行隊(duì)列,牛逼之處在于它管理必須在主線程中執(zhí)行的任務(wù),屬于有勞保的。

全局隊(duì)列:系統(tǒng)為我們創(chuàng)建好的一個(gè)并行隊(duì)列,使用起來(lái)與我們自己創(chuàng)建的并行隊(duì)列無(wú)本質(zhì)差別。

2NSThread
@interface NSThread : NSObject
//當(dāng)前線程
@property (class, readonly, strong) NSThread *currentThread;
//使用類方法創(chuàng)建線程執(zhí)行任務(wù)

  • (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
  • (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
    //判斷當(dāng)前是否為多線程
  • (BOOL)isMultiThreaded;
    //指定線程的線程參數(shù),例如設(shè)置當(dāng)前線程的斷言處理器。
    @property (readonly, retain) NSMutableDictionary *threadDictionary;
    //當(dāng)前線程暫停到某個(gè)時(shí)間
  • (void)sleepUntilDate:(NSDate *)date;
    //當(dāng)前線程暫停一段時(shí)間
  • (void)sleepForTimeInterval:(NSTimeInterval)ti;
    //退出當(dāng)前線程
  • (void)exit;
    //當(dāng)前線程優(yōu)先級(jí)
  • (double)threadPriority;
    //設(shè)置當(dāng)前線程優(yōu)先級(jí)
  • (BOOL)setThreadPriority:(double)p;
    //指定線程對(duì)象優(yōu)先級(jí) 0.0~1.0,默認(rèn)值為0.5
    @property double threadPriority NS_AVAILABLE(10_6, 4_0);
    //服務(wù)質(zhì)量
    @property NSQualityOfService qualityOfService NS_AVAILABLE(10_10, 8_0);
    //線程名稱
    @property (nullable, copy) NSString *name NS_AVAILABLE(10_5, 2_0);
    //棧區(qū)大小
    @property NSUInteger stackSize NS_AVAILABLE(10_5, 2_0);
    //是否為主線程
    @property (class, readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0);
    //獲取主線程
    @property (class, readonly, strong) NSThread *mainThread NS_AVAILABLE(10_5, 2_0);
    //初始化
  • (instancetype)init NS_AVAILABLE(10_5, 2_0) NS_DESIGNATED_INITIALIZER;
    //實(shí)例方法初始化,需要再調(diào)用start方法
  • (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument NS_AVAILABLE(10_5, 2_0);
  • (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
    //線程狀態(tài),正在執(zhí)行
    @property (readonly, getter=isExecuting) BOOL executing NS_AVAILABLE(10_5, 2_0);
    //線程狀態(tài),正在完成
    @property (readonly, getter=isFinished) BOOL finished NS_AVAILABLE(10_5, 2_0);
    //線程狀態(tài),已經(jīng)取消
    @property (readonly, getter=isCancelled) BOOL cancelled NS_AVAILABLE(10_5, 2_0);
    //取消,僅僅改變線程狀態(tài),并不能像exist一樣真正的終止線程
  • (void)cancel NS_AVAILABLE(10_5, 2_0);
    //開(kāi)始
  • (void)start NS_AVAILABLE(10_5, 2_0);
    //線程需要執(zhí)行的代碼,一般寫子類的時(shí)候會(huì)用到
  • (void)main NS_AVAILABLE(10_5, 2_0);
    @end
    另外,還有一個(gè)NSObject的分類,瞅一眼:
    @interface NSObject (NSThreadPerformAdditions)
    //隱式的創(chuàng)建并啟動(dòng)線程,并在指定的線程(主線程或子線程)上執(zhí)行方法。
  • (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array;
  • (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
  • (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array NS_AVAILABLE(10_5, 2_0);
  • (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
  • (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg NS_AVAILABLE(10_5, 2_0);
    @end
  1. 對(duì)于單核CPU來(lái)說(shuō),不存在真正意義上的并行,所以,多線程執(zhí)行任務(wù),其實(shí)也只是一個(gè)人在干活,CPU的調(diào)度決定了非等待任務(wù)的執(zhí)行速率,同時(shí)對(duì)于非等待任務(wù),多線程并沒(méi)有真正意義提高效率。

  2. 線程可以簡(jiǎn)單的認(rèn)為就是一段代碼+運(yùn)行時(shí)數(shù)據(jù)。

  3. 同步執(zhí)行會(huì)在當(dāng)前線程執(zhí)行任務(wù),不具備開(kāi)辟線程的能力或者說(shuō)沒(méi)有必要開(kāi)辟新的線程。并且,同步執(zhí)行必須等到Block函數(shù)執(zhí)行完畢,dispatch函數(shù)才會(huì)返回,從而阻塞同一串行隊(duì)列中外部方法的執(zhí)行。

  4. 異步執(zhí)行dispatch函數(shù)會(huì)直接返回,Block函數(shù)我們可以認(rèn)為它會(huì)在下一幀加入隊(duì)列,并根據(jù)所在隊(duì)列目前的任務(wù)情況無(wú)限下一幀執(zhí)行,從而不會(huì)阻塞當(dāng)前外部任務(wù)的執(zhí)行。同時(shí),只有異步執(zhí)行才有開(kāi)辟新線程的必要,但是異步執(zhí)行不一定會(huì)開(kāi)辟新線程。

  5. 只要是隊(duì)列,肯定是FIFO(先進(jìn)先出),但是誰(shuí)先執(zhí)行完要看第1條。

  6. 只要是串行隊(duì)列,肯定要等上一個(gè)任務(wù)執(zhí)行完成,才能開(kāi)始下一個(gè)任務(wù)。但是并行隊(duì)列當(dāng)上一個(gè)任務(wù)開(kāi)始執(zhí)行后,下一個(gè)任務(wù)就可以開(kāi)始執(zhí)行。

  7. 想要開(kāi)辟新線程必須讓任務(wù)在異步執(zhí)行,想要開(kāi)辟多個(gè)線程,只有讓任務(wù)在并行隊(duì)列中異步執(zhí)行才可以。執(zhí)行方式和隊(duì)列類型多層組合在一定程度上能夠?qū)崿F(xiàn)對(duì)于代碼執(zhí)行順序的調(diào)度。

  8. 同步+串行:未開(kāi)辟新線程,串行執(zhí)行任務(wù);同步+并行:未開(kāi)辟新線程,串行執(zhí)行任務(wù);異步+串行:新開(kāi)辟一條線程,串行執(zhí)行任務(wù);異步+并行:開(kāi)辟多條新線程,并行執(zhí)行任務(wù);在主線程中同步使用主隊(duì)列執(zhí)行任務(wù),會(huì)造成死鎖。

  9. 對(duì)于多核CPU來(lái)說(shuō),線程數(shù)量也不能無(wú)限開(kāi)辟,線程的開(kāi)辟同樣會(huì)消耗資源,過(guò)多線程同時(shí)處理任務(wù)并不是你想像中的人多力量大。

10.并行隊(duì)列+同步 不生成線程 并行隊(duì)列+異步 生成新的線程

GCD其他函數(shù)用法

  1. dispatch_after

該函數(shù)用于任務(wù)延時(shí)執(zhí)行,其中參數(shù)dispatch_time_t代表延時(shí)時(shí)長(zhǎng),dispatch_queue_t代表使用哪個(gè)隊(duì)列。如果隊(duì)列未主隊(duì)列,那么任務(wù)在主線程執(zhí)行,如果隊(duì)列為全局隊(duì)列或者自己創(chuàng)建的隊(duì)列,那么任務(wù)在子線程執(zhí)行,代碼如下:

-(void)GCDDelay{
//主隊(duì)列延時(shí)
dispatch_time_t when_main = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(when_main, dispatch_get_main_queue(), ^{
NSLog(@"main_%@",[NSThread currentThread]);
});
//全局隊(duì)列延時(shí)
dispatch_time_t when_global = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC));
dispatch_after(when_global, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"global_%@",[NSThread currentThread]);
});
//自定義隊(duì)列延時(shí)
dispatch_time_t when_custom = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC));
dispatch_after(when_custom, self.serialQueue, ^{
NSLog(@"custom_%@",[NSThread currentThread]);
});
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容