iOS之多線程

1.進(jìn)程與線程的區(qū)別與聯(lián)系

1.1.進(jìn)程

廣義上來講,進(jìn)程是系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序,每個(gè)進(jìn)程間都是獨(dú)立的,每個(gè)進(jìn)程都是運(yùn)行在獨(dú)有的空間內(nèi),空間是受保護(hù)的,這就意味著一個(gè)進(jìn)程是不能訪問另一個(gè)進(jìn)程的獨(dú)有空間的。平時(shí)接觸到的應(yīng)用程序都可以認(rèn)為是一個(gè)進(jìn)程,比如Xcode,SourceTree等??梢酝ㄟ^活動(dòng)監(jiān)視器查看Mac上運(yùn)行的進(jìn)程。

進(jìn)程的五態(tài)模型:

  • 進(jìn)程的五態(tài)模型

1.2.線程

  • 線程是進(jìn)程的基本執(zhí)行單元
  • 進(jìn)程的所有任務(wù)都在線程中執(zhí)行,就是說一個(gè)進(jìn)程想執(zhí)行任務(wù)必須有一個(gè)線程,通常是主線程,也就是iOS中的UI線程

1.3.進(jìn)程與線程的關(guān)系

進(jìn)程與線程的關(guān)系

2.任務(wù)執(zhí)行的方式

2.1.串行

  • 串行

2.2.并行

  • 并行

3.多線程的實(shí)現(xiàn)方案

3.1.pThread

基于c的,沒用過,不解釋,有興趣的可以研究下#import <pthread.h>

3.2.NSThread

3.2.1.類方法

無返回值,自動(dòng)異步執(zhí)行。但無法設(shè)置屬性

+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
+ (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

3.2.2.實(shí)例方法

需要手動(dòng)調(diào)用start異步執(zhí)行,因?yàn)橛蟹祷刂?,所以可以設(shè)置屬性

- (instancetype)init NS_AVAILABLE(10_5, 2_0) NS_DESIGNATED_INITIALIZER;
- (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));

3.2.3.NSObject的category方法

以下方法的aSelector均不能有返回值,如果arg不為空則設(shè)置一個(gè)id類型參數(shù),否則不可設(shè)置參數(shù)。arg為執(zhí)行aSelector的入?yún)ⅰ?/p>

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
    // equivalent to the first method with kCFRunLoopCommonModes

wait參數(shù):如果在子線程執(zhí)行以上兩個(gè)方法,YES代表阻塞當(dāng)前子線程直到主線程的aSelector執(zhí)行完畢,NO代表不阻塞當(dāng)前子線程;如果在主線程執(zhí)行以上兩個(gè)方法,YES代表阻塞當(dāng)前主線程的方法執(zhí)行直到主線程的aSelector執(zhí)行完畢,NO代表不阻塞當(dāng)前主線程,也就是當(dāng)前主線程的方法執(zhí)行完畢再執(zhí)行aSelector

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)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);
    // equivalent to the first method with kCFRunLoopCommonModes

thr:多了個(gè)線程參數(shù)。

- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg NS_AVAILABLE(10_5, 2_0);

創(chuàng)建一個(gè)子線程執(zhí)行

3.3.GCD

3.3.1串行與并行

使用串行隊(duì)列執(zhí)行任務(wù)只會(huì)創(chuàng)建一個(gè)線程。

dispatch_queue_t serialQueue = dispatch_queue_create("com.gcd.queue.serial", DISPATCH_QUEUE_SERIAL);
dispatch_get_main_queue()

使用并行隊(duì)列會(huì)創(chuàng)建多個(gè)線程

dispatch_queue_t concurrentQueue = dispatch_queue_create("com.gcd.queue.concurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_get_global_queue(0, 0)

Xcode的log會(huì)顯示進(jìn)程與線程ID


進(jìn)程:2055;線程:91668

3.3.2.dispatch_group

當(dāng)多個(gè)任務(wù)dispatch_group_async執(zhí)行完畢后會(huì)在dispatch_group_notify回調(diào)。但是注意dispatch_group_async中執(zhí)行的應(yīng)該是同步的代碼,如果是異步的代碼比如本身就是異步的網(wǎng)絡(luò)請求不會(huì)達(dá)到請求完畢的回調(diào)效果。
如果要達(dá)到上述效果,需要如下操作

- (void)GCDAction{
    
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_enter(group);
    [self request1:^{
        NSLog(@"request1 done");
        dispatch_group_leave(group);
    }];
    
    dispatch_group_enter(group);
    [self request2:^{
        NSLog(@"request2 done");
        dispatch_group_leave(group);
    }];
    
    dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"回調(diào)完成");
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"回到主線程刷新UI");
        });
    });
    
}

- (void)request1:(void(^)())block{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"start task 1");
        sleep(2);
        NSLog(@"end task 1");
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if (block) {
                block();
            }
        });
    });
}

- (void)request2:(void(^)())block{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"start task 2");
        sleep(2);
        NSLog(@"end task 2");
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if (block) {
                block();
            }
        });
    });
}
打印的log

3.4.NSOperation

NSOperation是對GCD的面向?qū)ο蟮姆庋b。

3.4.1.NSInvocationOperation

NSInvocationOperation會(huì)阻塞當(dāng)前線程同步執(zhí)行。

3.4.2.NSBlockOperation

NSInvocationOperation一樣會(huì)阻塞當(dāng)前線程同步執(zhí)行。

3.4.3.NSOperationQueue

如果想要異步執(zhí)行,需要使用NSOperationQueue的以下方法來實(shí)現(xiàn)。

- (void)addOperation:(NSOperation *)op;
- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait NS_AVAILABLE(10_6, 4_0);
- (void)addOperationWithBlock:(void (^)(void))block NS_AVAILABLE(10_6, 4_0);

3.4.4.自定義NSOperation

自定義的NSOperation需要重寫- (void)main方法,方法里面是具體的業(yè)務(wù)實(shí)現(xiàn)。對于設(shè)置異步的依賴不起作用的問題,可以這樣實(shí)現(xiàn)。

#import "CustomOperation.h"

@interface CustomOperation ()
@property (nonatomic, assign) BOOL over;
@end

@implementation CustomOperation

- (void)main{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        sleep(1);
        if (self.isCancelled) {
            return ;
        }
        
        NSLog(@"%@", self.name);
        self.over = YES;
    });
    
    while (!self.over && !self.isCancelled) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
}

@end
- (void)NSOperationAction{
    
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    CustomOperation *op1 = [[CustomOperation alloc]init];
    op1.name = @"op1";
    
    CustomOperation *op2 = [[CustomOperation alloc]init];
    op2.name = @"op2";
    
    CustomOperation *op3 = [[CustomOperation alloc]init];
    op3.name = @"op3";
    
    CustomOperation *op4 = [[CustomOperation alloc]init];
    op4.name = @"op4";
    
    [op1 addDependency:op2];
    [op2 addDependency:op3];
    [op3 addDependency:op4];
    
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
    [queue addOperation:op4];
}

Xcode打印日志

依賴關(guān)系

上一篇:iOS圖片濾鏡

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

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

  • 進(jìn)程和線程 首先,在了解多線程之前要了解什么是進(jìn)程,什么是線程 什么是進(jìn)程呢?進(jìn)程是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程...
    擱淺的青蛙閱讀 461評論 0 0
  • 前言 iOS多線程有四種:pthread(最古老的),NSThread,NSOperation,GCD 一、進(jìn)程和...
    GitHubPorter閱讀 403評論 0 3
  • 很多人都寫過多線程的文章,今天我也來小小的總結(jié)一下: 多線程基本概念 1個(gè)應(yīng)用程序要想執(zhí)行任務(wù),必須得有線程(每1...
    李小南閱讀 1,047評論 4 39
  • 多線程 在iOS開發(fā)中為提高程序的運(yùn)行效率會(huì)將比較耗時(shí)的操作放在子線程中執(zhí)行,iOS系統(tǒng)進(jìn)程默認(rèn)啟動(dòng)一個(gè)主線程,用...
    郭豪豪閱讀 2,720評論 0 4
  • 原文地址 http://www.cnblogs.com/kenshincui/p/3983982.html 大家都...
    怎樣m閱讀 1,423評論 0 1

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