iOS中NSOperation使用
在前面介绍了
NSThread的使用 ,
GCD的使用,
接下来我们将介绍NSOperation的使用
简介
在iOS的多线程开发过程中,不可避免的要使用多线程,多线程可以在不阻塞主线程的前提下提高效率。在这里呢,我们将看看多线程中NSOperation是如何使用的。
NSInvocationOperation
The NSInvocationOperation
class is a concrete subclass of NSOperation that you use to initiate an operation that consists of invoking a selector on a specified object. This class implements a non-concurrent operation.
根据苹果官方的解释说,NSInvocationOperation
是NSOperation
的一个子类,你可以初始化一个操作,该操作在一个指定的对象上去调用一个selector,并且NSOperation
这个类实现了一个非并发的操作。具体怎么使用NSInvocationOperation
这个类呢?
NSInvocationOperation的创建
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest) object:nil];
NSInvocationOperation创建完成之后,怎么触发该线程的执行?一共有两种方式执行该线程
方式一:
//调用start方法执行,此执行方式在主线程中执行,没有开辟新的线程
// ThreadDemo[20397:12090175] ------------<NSThread: 0x60400007da00>{number = 1, name = main}-----
[operation start];
调用start方法执行此线程,但是使用此方法,并不会开辟新的线程来执行代码
方式二:
//加入到队列中去执行,此种方式会开辟线程,在新的线程中执行代码
// ThreadDemo[20432:12091400] ------------<NSThread: 0x600000273240>{number = 3, name = (null)}-----
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
根据打印信息可以看出,把创建的NSInvocationOperation加入到一个queue队列中去执行,会开辟新的线程执行任务。
NSBlockOperation
The NSBlockOperation
class is a concrete subclass of NSOperationthat manages the concurrent execution of one or more blocks. You can use this object to execute several blocks at once without having to create separate operation objects for each. When executing more than one block, the operation itself is considered finished only when all blocks have finished executing.
NSBlockOperation
类是NSOperation
的一个具体子类,它管理一个或多个块的并发执行。您可以使用这个对象一次执行几个块,而不必为每个块创建单独的操作对象。当执行多个块时,只有当所有块都完成执行时,才考虑操作本身。
NSBlockOperation的创建
//创建NSBlockOperation线程方式1
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation------%@-----", [NSThread currentThread]);
}];
[operation start];
//创建NSBlockOperation线程方式2
NSBlockOperation *operation1 = [[NSBlockOperation alloc] init];
[operation1 addExecutionBlock:^{
NSLog(@"------operation1------%@-----", [NSThread currentThread]);
}];
[operation1 start];
这样创建后调用start方法,同样在主线程中执行,下面看看把NSBlockOperation添加到queue队列中去执行
NSBlockOperation *operation = [[NSBlockOperation alloc] init];
[operation addExecutionBlock:^{
NSLog(@"------block1------%@-----", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"------block2------%@-----", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"------block3------%@-----", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"------block4------%@-----", [NSThread currentThread]);
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
可以看出,加入到queue队列中的任务全都是异步执行
使用NSOperationQueue来创建任务
/**
使用queue队列来自己添加任务并执行
*/
- (void)testOperationQueue {
//创建queue队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//添加任务
[queue addOperationWithBlock:^{
NSLog(@"------block1------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block2------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block3------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block4------%@-----", [NSThread currentThread]);
}];
}
可以看出,使用queue队列来创建任务,省去了创建NSInvocationOperation
和NSBlockOperation
再加入到队列中执行。
上面列出了三种实现NSOperation
创建多线程的方式,在具体的工作中,使用哪种方式还是要根据工作需要具体对待。
队列的使用----依赖执行任务
有这个一个场景:任务3的执行依赖于任务2,任务2的执行依赖于任务1,相当于一个串行队列,只有当前面一个执行完成之后才开始下一个任务的执行,下面看看具体的实现方式:
/**
使用场景一:任务的依赖执行
*/
- (void)testDepenceyOperation {
//创建要执行的任务
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation1------%@-----", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation2------%@-----", [NSThread currentThread]);
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation3------%@-----", [NSThread currentThread]);
}];
//给任务添加依赖,任务3依赖任务2,任务2依赖任务1
[operation3 addDependency:operation2];
[operation2 addDependency:operation1];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}
队列的使用---设置最大并发数
设置最大并发数量,为了保证app的整个生命周期不会占用过多的资源,在有大量并发线程执行的时候,一定要进行设置,不然可能会造成app闪退。
- (void)testMacConcurrentOperationCount {
//创建queue队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//设置线程的最大并发数量
queue.maxConcurrentOperationCount = 3;
//添加任务
[queue addOperationWithBlock:^{
NSLog(@"------block1------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block2------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block3------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block4------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block5------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block6------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block7------%@-----", [NSThread currentThread]);
}];
}
最后附上以上代码链接
上述所有代码均可以在NSOperationDemo中查看,有需要可以自行获取