您的位置:首页 > 移动开发 > IOS开发

总结iOS 多线程学习过程六

2015-11-16 20:02 375 查看
iOS多线程的老二 ---- NSOperation

老二存在的意义:

1. 是完全面向对象

2. 包含GCD 无法实现的功能:

    1) 指定使用线程的个数

    2) 任务间的依赖关系

选择 GCD 还是 NSoperation?

能用老大用老大,老大不行老二上.....

首先介绍 NSOperation 的一个子类:

------ NSInvocationOperation

上代码:- (void)viewDidLoad {
[super viewDidLoad];

}
//non-main queue
- (IBAction)invocationSync:(id)sender {
//1.创建非主队列
//2.创建NSInvocationOperation对象
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(printPlus) object:nil];
//3.指定执行的任务(直接添加到主队列中执行;sync同步执行)
[operation start];
}

- (IBAction)invocationAsync:(id)sender {
//1.创建非主队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//2.创建NSInvocationOperation对象
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(printPlus) object:nil];
NSInvocationOperation *secondOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(printMinus) object:nil];
//3.指定执行的任务(添加的瞬间就异步执行)
[queue addOperation:operation];
[queue addOperation:secondOperation];
NSLog(@"执行完毕");

}
- (void)printMinus {
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:1];
NSLog(@"---------%@", [NSThread currentThread]);
}
}
- (void)printPlus {
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:1];
NSLog(@"++++++++++%@", [NSThread currentThread]);
}
}


执行结果:
2015-11-16 20:27:51.460 pthread[2116:198665] ++++++++++<NSThread: 0x7fac28605c90>{number = 1, name = main}

2015-11-16 20:27:52.461 pthread[2116:198665] ++++++++++<NSThread: 0x7fac28605c90>{number = 1, name = main}

2015-11-16 20:27:53.461 pthread[2116:198665] ++++++++++<NSThread: 0x7fac28605c90>{number = 1, name = main}

2015-11-16 20:27:54.462 pthread[2116:198665] ++++++++++<NSThread: 0x7fac28605c90>{number = 1, name = main}

2015-11-16 20:27:55.463 pthread[2116:198665] ++++++++++<NSThread: 0x7fac28605c90>{number = 1, name = main}

2015-11-16 20:27:57.283 pthread[2116:198665] 执行完毕

2015-11-16 20:27:58.305 pthread[2116:198785] ---------<NSThread: 0x7fac2850a0e0>{number = 2, name = (null)}

2015-11-16 20:27:58.305 pthread[2116:198782] ++++++++++<NSThread: 0x7fac286132f0>{number = 3, name = (null)}

2015-11-16 20:27:59.373 pthread[2116:198782] ++++++++++<NSThread: 0x7fac286132f0>{number = 3, name = (null)}

2015-11-16 20:27:59.373 pthread[2116:198785] ---------<NSThread: 0x7fac2850a0e0>{number = 2, name = (null)}

2015-11-16 20:28:00.446 pthread[2116:198785] ---------<NSThread: 0x7fac2850a0e0>{number = 2, name = (null)}

2015-11-16 20:28:00.446 pthread[2116:198782] ++++++++++<NSThread: 0x7fac286132f0>{number = 3, name = (null)}

2015-11-16 20:28:01.521 pthread[2116:198785] ---------<NSThread: 0x7fac2850a0e0>{number = 2, name = (null)}

2015-11-16 20:28:01.521 pthread[2116:198782] ++++++++++<NSThread: 0x7fac286132f0>{number = 3, name = (null)}

2015-11-16 20:28:02.595 pthread[2116:198785] ---------<NSThread: 0x7fac2850a0e0>{number = 2, name = (null)}

2015-11-16 20:28:02.595 pthread[2116:198782] ++++++++++<NSThread: 0x7fac286132f0>{number = 3, name = (null)}

由结果可知,,当使用 start 方法启动时,他是在默认的线程中的,,而加到自己建的 NSOperationQueue *queue 中是在子线程中执行的.

第二个子类:

------ NSBlockOperation

上代码:

<span style="font-size:18px;">- (void)viewDidLoad {
[super viewDidLoad];

}
- (IBAction)blockSync:(id)sender {
//创建对象(方式一)
NSBlockOperation *operation = [NSBlockOperation new];
//添加任务
[operation addExecutionBlock:^{
NSLog(@"下载图片111111%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"下载图片2222%@", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"下载图片3333%@", [NSThread currentThread]);
}];
//执行任务(同步)
//第一个操作由主线程做; 剩余操作由子线程做
[operation start];
}

- (IBAction)blockAsync:(id)sender {
//1.创建一个非主队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//2.创建操作对象(方式二)
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片1111%@", [NSThread currentThread]);
}];
NSBlockOperation *otherOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片2222%@", [NSThread currentThread]);
}];
//3.执行操作(添加操作到非主队列)
[queue addOperation:operation];
[queue addOperation:otherOperation];
NSLog(@"下载完毕");
}</span>
执行结果:
2015-11-16 20:36:55.236 pthread[2150:203509] 下载图片111111<NSThread: 0x7fb1527050d0>{number = 1, name = main}

2015-11-16 20:36:55.236 pthread[2150:204161] 下载图片2222<NSThread: 0x7fb1526542d0>{number = 3, name = (null)}

2015-11-16 20:36:55.236 pthread[2150:204164] 下载图片3333<NSThread: 0x7fb152422990>{number = 2, name = (null)}

2015-11-16 20:37:01.211 pthread[2150:203509] 下载完毕

2015-11-16 20:37:01.211 pthread[2150:204161] 下载图片1111<NSThread: 0x7fb1526542d0>{number = 3, name = (null)}

2015-11-16 20:37:01.211 pthread[2150:204164] 下载图片2222<NSThread: 0x7fb152422990>{number = 2, name = (null)}

要注意NSBlockOperation 中 start 的方法,他是把第一个交由主线程,剩下的在子线程中完成

由上面两个例子,你应该也知道了 NSOperation 是不创建对象的,因为他是个抽象类,创建对象都有他的子类完成

-----------------------------------------分割线-----------------------------------------

现在补充 NSOperation 比 GCD多出来的功能:

上代码:

- (void)viewDidLoad {
[super viewDidLoad];

}

- (IBAction)setConcurrentCount:(id)sender {
//创建非主队列
NSOperationQueue *queue = [NSOperationQueue new];
//设定同时执行任务的个数(起多少子线程)
queue.maxConcurrentOperationCount = 2;
//创建任务
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog
ac03
(@"下载图片11111%@",[NSThread currentThread]);
}];
NSBlockOperation *secondOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片2222%@", [NSThread currentThread]);
}];
NSBlockOperation *thirdOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片333%@", [NSThread currentThread]);
}];
NSBlockOperation *forthOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片4444%@",[NSThread currentThread]);
}];
NSBlockOperation *fifthOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片5555%@", [NSThread currentThread]);
}];
NSBlockOperation *sixthOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片666%@", [NSThread currentThread]);
}];
NSBlockOperation *seventhOperation= [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片777%@", [NSThread currentThread]);
}];
//执行任务(添加到非主队列)
NSArray *array = @[operation, secondOperation, thirdOperation, forthOperation, fifthOperation, sixthOperation, seventhOperation];
[queue addOperations:array waitUntilFinished:YES];
}

- (IBAction)setDependency:(id)sender {
//设定非主队列中的任务的依赖关系
/*task1, task2, task3 ---> 三个同时执行
需求1: task1 + task2 --> task3
task3 依赖 task1
task3 依赖 task2
需求2: task2 --> task1 + task3
task1 依赖 task2
task3 依赖 task2
*/
//1.创建非主队列
NSOperationQueue *queue = [NSOperationQueue new];
//2.创建操作(任务/子线程)
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片11111");
}];
NSBlockOperation *secondOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片2222");
[NSThread sleepForTimeInterval:5];
}];
NSBlockOperation *thirdOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片333");
}];
//3.设定依赖关系
[thirdOperation addDependency:operation];
[thirdOperation addDependency:secondOperation];
//4.执行任务
[queue addOperation:operation];
[queue addOperation:secondOperation];
[queue addOperation:thirdOperation];
}

- (IBAction)returnMainThread:(id)sender {
//方式三: 回到主线程 (有且仅有一个主队列)
//非主队列
NSOperationQueue *queue = [NSOperationQueue new];
//添加任务(子线程)
[queue addOperationWithBlock:^{
NSLog(@"开始下载图片%@", [NSThread currentThread]);
//回到主线程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"显示/加载图片%@", [NSThread currentThread]);
}];
}];

}执行结果:
2015-11-16 20:43:50.972 Demo03-Block-Dependency[2195:208141] 下载图片2222<NSThread: 0x7fae0af06ac0>{number = 2, name = (null)}

2015-11-16 20:43:50.972 Demo03-Block-Dependency[2195:208144] 下载图片11111<NSThread: 0x7fae0ac26350>{number = 3, name = (null)}

2015-11-16 20:43:50.973 Demo03-Block-Dependency[2195:208144] 下载图片333<NSThread: 0x7fae0ac26350>{number = 3, name = (null)}

2015-11-16 20:43:50.973 Demo03-Block-Dependency[2195:208149] 下载图片4444<NSThread: 0x7fae0ae70bf0>{number = 4, name = (null)}

2015-11-16 20:43:50.973 Demo03-Block-Dependency[2195:208144] 下载图片5555<NSThread: 0x7fae0ac26350>{number = 3, name = (null)}

2015-11-16 20:43:50.973 Demo03-Block-Dependency[2195:208141] 下载图片666<NSThread: 0x7fae0af06ac0>{number = 2, name = (null)}

2015-11-16 20:43:50.973 Demo03-Block-Dependency[2195:208173] 下载图片777<NSThread: 0x7fae0ae71000>{number = 5, name = (null)}

2015-11-16 20:43:59.163 Demo03-Block-Dependency[2195:208173] 下载图片11111

2015-11-16 20:43:59.163 Demo03-Block-Dependency[2195:208144] 下载图片2222

2015-11-16 20:44:04.239 Demo03-Block-Dependency[2195:208144] 下载图片333

2015-11-16 20:44:19.827 Demo03-Block-Dependency[2195:208561] 开始下载图片<NSThread: 0x7fae0ac41ed0>{number = 6, name = (null)}

2015-11-16 20:44:19.828 Demo03-Block-Dependency[2195:208051] 显示/加载图片<NSThread: 0x7fae0ad040a0>{number = 1, name = main}

观察结果中,设置了线程并发个数后,单位时间内确实只有两个线程在工作;;;而依赖关系的设定能跟好的控制线程之间的先后顺序;;;最后是回到主线程的方法.

再来个回到主线程方法总结,因为前面少说了一种,现在在总结:

①:NSThread ---- [self performSelectorOnMainThread: withObject: waitUntilDone:] (之前少的);

②:GCD ---- dispatch_async(dispatch_get_main_queue(),^{    //code    });

③:NSOperation ---- [[NSOperationQueue mainQueue] addOperationWithBlock:^{    //code   
}];

多线程内容基本完成,,,,,,我只是小白一只,欢迎大家补充交流,共同提高
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息