1.進程與線程的區(qū)別與聯系
1.1.進程
廣義上來講楣号,進程是系統(tǒng)中正在運行的一個應用程序刽脖,每個進程間都是獨立的举庶,每個進程都是運行在獨有的空間內执隧,空間是受保護的,這就意味著一個進程是不能訪問另一個進程的獨有空間的户侥。平時接觸到的應用程序都可以認為是一個進程镀琉,比如Xcode,SourceTree等蕊唐∥菟ぃ可以通過活動監(jiān)視器查看Mac上運行的進程。
進程的五態(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
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();
}
});
});
}
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圖片濾鏡