多线程之-NSOperation

NSOperation

1.和NSThread,GCD一样,NSOperation也是苹果提供的一套多线程并发编程方案;
2.它是对GCD在OC层面的一个封装,是完全面向对象的;
3.它比GCD多了一些更加实用的功能;
4.经常使用;
5.自动管理;

NSOperation用法

NSOperation是一个抽象类,在使用的时候,需要使用的是它的子类,并且有3种方式:

1.NSInvocationOperation类;
2.NSBlockOperation类;
3.继承于NSOperation的子类,重写main方法;

要实现多线程,需要配合NSOperationQueue类进行配合;
NSOperationQueue表示队列,分为主队列和其他队列:

主队列是一个特殊的串行队列;
其他队列包含了串行队列和并发队列;

NSOperationQueue

获取主队列:

1
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];

其他队列:

1
2
NSOperationQueue *q1 = [[NSOperationQueue alloc]init];
q1.maxConcurrentOperationCount = 1;

maxConcurrentOperationCount属性:
线程的最大个数,该属性不进行设置时,默认为-1即为并发队列,不限制线程开启个数,开启新线程;
当值为1时,表示为串行队列,虽然开启了线程,但是是一个一个执行;
不要无脑的认为设置该值越大,开启的线程数量就越多,线程开启最大数系统会自行调整;

其他方法:

1
2
3
4
5
6
7
8
9
10
11
12
//队列添加任务,并自动开启
- (void)addOperation:(NSOperation *)op;
//添加任务数组,wait=YES的时候,阻塞线程,表示等待任务完成再往下操作
- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait;
//直接开始任务操作,会开始新的线程
- (void)addOperationWithBlock:(void (^)(void))block;
//YES表示暂停,设置为NO可以恢复
@property (getter=isSuspended) BOOL suspended;
//已经加入到队列的任务无法删除,但是可以暂停,下面表示暂停当前队列所有的任务,当然,已经开始的任务是无法暂停的
- (void)cancelAllOperations;
//等待队列中所有任务的完成,会阻塞线程
- (void)waitUntilAllOperationsAreFinished;
NSInvocationOperation使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//队列,默认并发
NSOperationQueue *q1 = [[NSOperationQueue alloc]init];
//创建
NSInvocationOperation *invocationOperation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(invationAction1) object:nil];
//队列添加任务并开始
[q1 addOperation:invocationOperation1];
-(void)invationAction1{
for (NSUInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"Invocation1 = %@",[NSThread currentThread]);
}
}

2018-08-06 16:38:39.462458+0800 FDThread[7300:689575] Invocation1 = <NSThread: 0x600003b7a7c0>{number = 4, name = (null)}
2018-08-06 16:38:41.464461+0800 FDThread[7300:689575] Invocation1 = <NSThread: 0x600003b7a7c0>{number = 4, name = (null)}

开启的了新的线程;

NSBlockOperation使用
1
2
3
4
5
6
7
8
9
10
11
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
for (NSUInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"block1 = %@",[NSThread currentThread]);
}

}];
[q1 addOperation:block1];

2018-08-06 16:38:43.467961+0800 FDThread[7300:689574] block1 = <NSThread: 0x600003b6f7c0>{number = 5, name = (null)}
2018-08-06 16:38:45.469692+0800 FDThread[7300:689574] block1 = <NSThread: 0x600003b6f7c0>{number = 5, name = (null)}
自定义NSOperation子类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.h
@interface CoustomOperation : NSOperation

@end
.m
@implementation CoustomOperation
//重写main方法,进行相关操作
-(void)main{
for (NSUInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"CoustomOperation = %@",[NSThread currentThread]);
}
}
@end

CoustomOperation *c1 = [[CoustomOperation alloc]init];
[q1 addOperation:c1];

2018-08-06 16:38:47.473828+0800 FDThread[7300:689574] CoustomOperation = <NSThread: 0x600003b6f7c0>{number = 5, name = (null)}
2018-08-06 16:38:49.477721+0800 FDThread[7300:689574] CoustomOperation = <NSThread: 0x600003b6f7c0>{number = 5, name = (null)}
NSOperationQueue的方法
1
2
3
4
5
6
7
8
9
10
11
12
NSOperationQueue *q2 = [[NSOperationQueue alloc]init];
[q2 addOperationWithBlock:^{
//直接添加任务,会开启新线程
for (NSUInteger i = 0; i < 2; i ++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"queue = %@",[NSThread currentThread]);

}
}];

2018-08-06 16:38:39.462458+0800 FDThread[7300:689576] queue = <NSThread: 0x600003b8e000>{number = 3, name = (null)}
2018-08-06 16:38:41.464419+0800 FDThread[7300:689576] queue = <NSThread: 0x600003b8e000>{number = 3, name = (null)}
不同操作队列任务之间可以设置依赖

设置依赖的意思就是可以设置某个任务的开始执行依赖于另外一个任务的完成

1
2
3
4
//blcok1 任务会在invocationOperation1所有任务完成之后才开始执行
[block1 addDependency:invocationOperation1];
//可以移除依赖
- (void)removeDependency:(NSOperation *)op;
NSOperation其他的一些设置
1
2
3
4
5
6
7
8
9
10
11
12
13
//设置任务的优先级,默认NSOperationQueuePriorityNormal,优先级高只表明优先被执行,而不代表被完成,在
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
};
@property NSOperationQueuePriority queuePriority;
//获取某个任务的所有依赖,只读属性
@property (readonly, copy) NSArray<NSOperation *> *dependencies;
//等待某个任务完成,会阻塞主线程
- (void)waitUntilFinished