在ios多线程中,会涉及到pthread、NSThread、GCD、NSOperation,本文主要介绍NSOperation。
一、队列(分为两种)
主队列:很明显,加入主队列的任务会在主线程同步执行。
非主队列:一般加入非主队列的任务,都会开启新线程异步执行。
二、NSOperation的基本用法
1.NSInvocationOperation的两种用法
- 直接调用start
- (void)testInvocationOperation1{
// 创建操作任务
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download:) object:@"www.testpng.com"];
// operation直接调用start,是同步执行(在当前线程执行操作),不会开启新线程
[operation start];
}
- (void)download:(NSString *)url{
NSLog(@"download-----%@---%@", [NSThread currentThread],url);
}
- 把operation放入队列中执行
- (void)testInvocationOperation2{
// 创建队列(非主队列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 创建操作任务
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download:) object:@"www.testpng.com"];
// 添加操作到队列中,会自动异步执行
[queue addOperation:operation];
}
- (void)download:(NSString *)url{
NSLog(@"download-----%@---%@", [NSThread currentThread],url);
}
2.NSBlockOperation的两种用法
- 也是直接调start方法
- (void)testBlockOperation1{
// 直接调用start方法时,只有任务数量大于1是,才会开始开启新线程异步执行
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---下载----1---%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"---下载----2---%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"---下载----3---%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"---下载----4---%@", [NSThread currentThread]);
}];
[operation start];
}
- 把操作放入队列中执行
- (void)testBlockOperation2{
// 1.创建队列操作任务
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---下载----1---%@", [NSThread currentThread]);
}];
[operation1 addExecutionBlock:^{
NSLog(@"---下载----2---%@", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---下载----3---%@", [NSThread currentThread]);
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---下载----4---%@", [NSThread currentThread]);
}];
NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"---下载----5---%@", [NSThread currentThread]);
}];
// 2.创建队列(非主队列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 3.添加操作到队列中(会开启新线程异步执行)
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
[queue addOperation:operation4];
}
- 自定义operation
这种情况用的比较多,SDWebImage下载网络图片就是用这种。
这种用法一般都继承于NSOperation,并重写main或start方法(只要operation加入队列中就会触发这两个方法)。我写了个NSOperationDemo ,有兴趣可以看下。
三、队列的用法
1. 可以设置最大并发(最多同时并发执行几个任务)。
这可以提高完成任务效率,这在SDWebImage也有体现。
2.可以随时暂时、恢复和取消队列中的任务。
下载图片过程中,为了提高体验,一般都会在拖拽scrollView时暂停队列中的任务,停止滚动时恢复任务,当收到内存警告时,取消队列中所有任务(一旦取消,不可恢复)。
3.在异步执行中,要顺序执行,可以设置依赖
- (void)testDependency{
// 1.创建一个队列(非主队列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.创建操作任务
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"先执行任务1---%@", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"再执行任务2---%@", [NSThread currentThread]);
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"最后再执行任务3---%@", [NSThread currentThread]);
}];
// 3.设置依赖
[operation2 addDependency:operation1];
[operation3 addDependency:operation2];
// 4.添加操作到队列中(自动异步执行任务)
[queue addOperation:operation3];
[queue addOperation:operation2];
[queue addOperation:operation1];
}