iOS之多線程

1.進程與線程的區(qū)別與聯系

1.1.進程

廣義上來講楣号,進程是系統(tǒng)中正在運行的一個應用程序刽脖,每個進程間都是獨立的举庶,每個進程都是運行在獨有的空間內执隧,空間是受保護的,這就意味著一個進程是不能訪問另一個進程的獨有空間的户侥。平時接觸到的應用程序都可以認為是一個進程镀琉,比如Xcode,SourceTree等蕊唐∥菟ぃ可以通過活動監(jiān)視器查看Mac上運行的進程。

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

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

1.2.線程

  • 線程是進程的基本執(zhí)行單元
  • 進程的所有任務都在線程中執(zhí)行替梨,就是說一個進程想執(zhí)行任務必須有一個線程钓试,通常是主線程,也就是iOS中的UI線程

1.3.進程與線程的關系

進程與線程的關系

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

2.1.串行

  • 串行

2.2.并行

  • 并行

3.多線程的實現方案

3.1.pThread

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

3.2.NSThread

3.2.1.類方法

無返回值俗扇,自動異步執(zhí)行硝烂。但無法設置屬性

+ (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.實例方法

需要手動調用start異步執(zhí)行,因為有返回值铜幽,所以可以設置屬性

- (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不為空則設置一個id類型參數,否則不可設置參數除抛。arg為執(zhí)行aSelector的入參狮杨。

- (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參數:如果在子線程執(zhí)行以上兩個方法,YES代表阻塞當前子線程直到主線程的aSelector執(zhí)行完畢到忽,NO代表不阻塞當前子線程橄教;如果在主線程執(zhí)行以上兩個方法清寇,YES代表阻塞當前主線程的方法執(zhí)行直到主線程的aSelector執(zhí)行完畢,NO代表不阻塞當前主線程护蝶,也就是當前主線程的方法執(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:多了個線程參數华烟。

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

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

3.3.GCD

3.3.1串行與并行

使用串行隊列執(zhí)行任務只會創(chuàng)建一個線程。

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

使用并行隊列會創(chuàng)建多個線程

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

Xcode的log會顯示進程與線程ID


進程:2055持灰;線程:91668

3.3.2.dispatch_group

當多個任務dispatch_group_async執(zhí)行完畢后會在dispatch_group_notify回調盔夜。但是注意dispatch_group_async中執(zhí)行的應該是同步的代碼,如果是異步的代碼比如本身就是異步的網絡請求不會達到請求完畢的回調效果堤魁。
如果要達到上述效果喂链,需要如下操作

- (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(@"回調完成");
        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的面向對象的封裝。

3.4.1.NSInvocationOperation

NSInvocationOperation會阻塞當前線程同步執(zhí)行妥泉。

3.4.2.NSBlockOperation

NSInvocationOperation一樣會阻塞當前線程同步執(zhí)行椭微。

3.4.3.NSOperationQueue

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

- (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è)務實現。對于設置異步的依賴不起作用的問題匈仗,可以這樣實現瓢剿。

#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打印日志

依賴關系

上一篇:iOS圖片濾鏡

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市悠轩,隨后出現的幾起案子间狂,更是在濱河造成了極大的恐慌,老刑警劉巖火架,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鉴象,死亡現場離奇詭異,居然都是意外死亡何鸡,警方通過查閱死者的電腦和手機纺弊,發(fā)現死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來骡男,“玉大人淆游,你說我怎么就攤上這事「羰ⅲ” “怎么了犹菱?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吮炕。 經常有香客問我腊脱,道長,這世上最難降的妖魔是什么龙亲? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任陕凹,我火速辦了婚禮悍抑,結果婚禮上,老公的妹妹穿的比我還像新娘杜耙。我一直安慰自己搜骡,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布泥技。 她就那樣靜靜地躺著浆兰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪珊豹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天榕订,我揣著相機與錄音店茶,去河邊找鬼。 笑死劫恒,一個胖子當著我的面吹牛贩幻,可吹牛的內容都是我干的。 我是一名探鬼主播两嘴,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼丛楚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了憔辫?” 一聲冷哼從身側響起趣些,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贰您,沒想到半個月后坏平,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡锦亦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年舶替,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杠园。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡顾瞪,死狀恐怖,靈堂內的尸體忽然破棺而出抛蚁,到底是詐尸還是另有隱情陈醒,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布篮绿,位于F島的核電站孵延,受9級特大地震影響,放射性物質發(fā)生泄漏亲配。R本人自食惡果不足惜尘应,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一惶凝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧犬钢,春花似錦苍鲜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至歹颓,卻和暖如春坯屿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巍扛。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工领跛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撤奸。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓吠昭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親胧瓜。 傳聞我的和親對象是個殘疾皇子矢棚,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容