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)系

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

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();
}
});
});
}

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

上一篇:iOS圖片濾鏡


