NSInvocationOperation
1、在主线程中使用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSURL *url = [NSURL URLWithString:@"abc"] ;
NSInvocationOperation *inv = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImgFromURL:) object:url];
[inv start];
}
- (void)downloadImgFromURL:(NSURL *)url {
NSLog(@"%@___%@",url,[NSThread currentThread]);
}
2018-10-10 14:29:42.285163+0800 Visit_Thread[4244:242395] abc___<NSThread: 0x60000006ea80>{number = 1, name = main}
2、多线程
当maxConcurrentOperationCount
小于当前任务数时会出现这样的情况(很容易理解3个任务,2条线程):
2条线程跑满2个任务,当一个线程中的任务执行完毕,再从队列中去取新的任务
如果设置最大并发数为1,那么任务将会串行执行(在不同的线程执行,但是执行顺序是串行的)
注意:串行执行任务 不等于 只开一条线程
如果设置最大并发数为0,那么任务将不会执行如果设置最大并发数为-1,表示最大并发数不受限制
- (void)test7 {
NSLog(@"start");
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount = 2;
NSURL *url = [NSURL URLWithString:@"abc"] ;
NSInvocationOperation *task1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImgFromURL1:) object:url];
[queue addOperation:task1];
NSInvocationOperation *task2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImgFromURL2:) object:url];
[queue addOperation:task2];
NSInvocationOperation *task3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImgFromURL3:) object:url];
[queue addOperation:task3];
NSLog(@"end");
}
- (void)downloadImgFromURL1:(NSURL *)url {
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1___%@",[NSThread currentThread]);
}
}
- (void)downloadImgFromURL2:(NSURL *)url {
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2___%@",[NSThread currentThread]);
}
}
- (void)downloadImgFromURL3:(NSURL *)url {
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3___%@",[NSThread currentThread]);
}
}
2018-10-10 14:58:31.460019+0800 Visit_Thread[4774:280702] start
2018-10-10 14:58:31.460932+0800 Visit_Thread[4774:280702] end
2018-10-10 14:58:33.463473+0800 Visit_Thread[4774:280744] 2___<NSThread: 0x60400007b840>{number = 3, name = (null)}
2018-10-10 14:58:33.463479+0800 Visit_Thread[4774:280746] 1___<NSThread: 0x60000066a980>{number = 4, name = (null)}
2018-10-10 14:58:35.468851+0800 Visit_Thread[4774:280744] 2___<NSThread: 0x60400007b840>{number = 3, name = (null)}
2018-10-10 14:58:35.468870+0800 Visit_Thread[4774:280746] 1___<NSThread: 0x60000066a980>{number = 4, name = (null)}
2018-10-10 14:58:37.474366+0800 Visit_Thread[4774:280746] 1___<NSThread: 0x60000066a980>{number = 4, name = (null)}
2018-10-10 14:58:37.474367+0800 Visit_Thread[4774:280744] 2___<NSThread: 0x60400007b840>{number = 3, name = (null)}
2018-10-10 14:58:39.479901+0800 Visit_Thread[4774:280744] 2___<NSThread: 0x60400007b840>{number = 3, name = (null)}
2018-10-10 14:58:39.479903+0800 Visit_Thread[4774:280745] 3___<NSThread: 0x60400026a700>{number = 5, name = (null)}
2018-10-10 14:58:41.485467+0800 Visit_Thread[4774:280745] 3___<NSThread: 0x60400026a700>{number = 5, name = (null)}
2018-10-10 14:58:41.485467+0800 Visit_Thread[4774:280744] 2___<NSThread: 0x60400007b840>{number = 3, name = (null)}
2018-10-10 14:58:43.491001+0800 Visit_Thread[4774:280745] 3___<NSThread: 0x60400026a700>{number = 5, name = (null)}
2018-10-10 14:58:45.496507+0800 Visit_Thread[4774:280745] 3___<NSThread: 0x60400026a700>{number = 5, name = (null)}
2018-10-10 14:58:47.502031+0800 Visit_Thread[4774:280745] 3___<NSThread: 0x60400026a700>{number = 5, name = (null)}
如果最大线程数超过当前任务数,那么也只会开和当前任务数相同的线程,多个任务,并发执行:
queue.maxConcurrentOperationCount = 5;
2018-10-10 15:02:01.148009+0800 Visit_Thread[4837:285412] start
2018-10-10 15:02:01.148893+0800 Visit_Thread[4837:285412] end
2018-10-10 15:02:03.152383+0800 Visit_Thread[4837:285465] 2___<NSThread: 0x60000047cf40>{number = 5, name = (null)}
2018-10-10 15:02:03.152388+0800 Visit_Thread[4837:285467] 1___<NSThread: 0x60000047cdc0>{number = 3, name = (null)}
2018-10-10 15:02:03.152383+0800 Visit_Thread[4837:285468] 3___<NSThread: 0x60400026d1c0>{number = 4, name = (null)}
2018-10-10 15:02:05.155475+0800 Visit_Thread[4837:285467] 1___<NSThread: 0x60000047cdc0>{number = 3, name = (null)}
2018-10-10 15:02:05.155489+0800 Visit_Thread[4837:285468] 3___<NSThread: 0x60400026d1c0>{number = 4, name = (null)}
2018-10-10 15:02:05.155481+0800 Visit_Thread[4837:285465] 2___<NSThread: 0x60000047cf40>{number = 5, name = (null)}
2018-10-10 15:02:07.159810+0800 Visit_Thread[4837:285465] 2___<NSThread: 0x60000047cf40>{number = 5, name = (null)}
2018-10-10 15:02:07.159821+0800 Visit_Thread[4837:285467] 1___<NSThread: 0x60000047cdc0>{number = 3, name = (null)}
2018-10-10 15:02:07.159815+0800 Visit_Thread[4837:285468] 3___<NSThread: 0x60400026d1c0>{number = 4, name = (null)}
2018-10-10 15:02:09.163067+0800 Visit_Thread[4837:285465] 2___<NSThread: 0x60000047cf40>{number = 5, name = (null)}
2018-10-10 15:02:09.163066+0800 Visit_Thread[4837:285468] 3___<NSThread: 0x60400026d1c0>{number = 4, name = (null)}
2018-10-10 15:02:11.168004+0800 Visit_Thread[4837:285468] 3___<NSThread: 0x60400026d1c0>{number = 4, name = (null)}
2018-10-10 15:02:11.168000+0800 Visit_Thread[4837:285465] 2___<NSThread: 0x60000047cf40>{number = 5, name = (null)}
NSBlockOperation
1、在主线程中使用
如果任务开始之后再追加任务,程序会cache:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSBlockOperation addExecutionBlock:]: blocks cannot be added after the operation has started executing or finished
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"start");
NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1___%@",[NSThread currentThread]);
}];
NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2___%@",[NSThread currentThread]);
}];
NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"3___%@",[NSThread currentThread]);
}];
//追加任务
[task1 addExecutionBlock:^{
NSLog(@"1+++%@",[NSThread currentThread]);
}];
[task2 addExecutionBlock:^{
NSLog(@"2+++%@",[NSThread currentThread]);
}];
[task3 addExecutionBlock:^{
NSLog(@"3+++%@",[NSThread currentThread]);
}];
[task3 start];//先开始,先执行
[task1 start];
[task2 start];
NSLog(@"end");
}
2018-10-10 14:41:09.361581+0800 Visit_Thread[4436:258615] start
2018-10-10 14:41:09.361974+0800 Visit_Thread[4436:258615] 3___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:41:09.361975+0800 Visit_Thread[4436:259265] 3+++<NSThread: 0x6000006667c0>{number = 8, name = (null)}
2018-10-10 14:41:09.362169+0800 Visit_Thread[4436:258615] 1___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:41:09.362182+0800 Visit_Thread[4436:259265] 1+++<NSThread: 0x6000006667c0>{number = 8, name = (null)}
2018-10-10 14:41:09.362635+0800 Visit_Thread[4436:259265] 2+++<NSThread: 0x6000006667c0>{number = 8, name = (null)}
2018-10-10 14:41:09.362643+0800 Visit_Thread[4436:258615] 2___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:41:09.362886+0800 Visit_Thread[4436:258615] end
2018-10-10 14:40:22.773672+0800 Visit_Thread[4436:258615] start
2018-10-10 14:40:22.774083+0800 Visit_Thread[4436:258615] 3___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:40:22.774114+0800 Visit_Thread[4436:258911] 3+++<NSThread: 0x60400046fc80>{number = 5, name = (null)}
2018-10-10 14:40:22.774752+0800 Visit_Thread[4436:258911] 1+++<NSThread: 0x60400046fc80>{number = 5, name = (null)}
2018-10-10 14:40:22.774753+0800 Visit_Thread[4436:258615] 1___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:40:22.774943+0800 Visit_Thread[4436:258615] 2___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:40:22.774951+0800 Visit_Thread[4436:258911] 2+++<NSThread: 0x60400046fc80>{number = 5, name = (null)}
2018-10-10 14:40:22.775110+0800 Visit_Thread[4436:258615] end
通过打印结果可知:先开始,先执行;
但是开始的任务中,是先执行原任务还是先执行追加任务,这个是不确定的;
原任务是在主线程中执行的,但是追加的任务都是在子线程中执行的;
多线程
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"start");
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// queue.maxConcurrentOperationCount = 5;
NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1___%@",[NSThread currentThread]);
}
}];
NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2___%@",[NSThread currentThread]);
}
}];
NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3___%@",[NSThread currentThread]);
}
}];
//追加任务
[task1 addExecutionBlock:^{
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:1];
NSLog(@"1+++%@",[NSThread currentThread]);
}
}];
[task2 addExecutionBlock:^{
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2+++%@",[NSThread currentThread]);
}
}];
[task3 addExecutionBlock:^{
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:3];
NSLog(@"3+++%@",[NSThread currentThread]);
}
}];
[queue addOperation:task1];
[queue addOperation:task2];
[queue addOperation:task3];
NSLog(@"end");
}
2018-10-10 15:13:38.464338+0800 Visit_Thread[5027:297309] start
2018-10-10 15:13:38.464920+0800 Visit_Thread[5027:297309] end
2018-10-10 15:13:39.465737+0800 Visit_Thread[5027:297386] 1+++<NSThread: 0x60400027e980>{number = 3, name = (null)}
2018-10-10 15:13:40.469689+0800 Visit_Thread[5027:297364] 2___<NSThread: 0x604000465c40>{number = 5, name = (null)}
2018-10-10 15:13:40.469701+0800 Visit_Thread[5027:297365] 1___<NSThread: 0x604000465b80>{number = 4, name = (null)}
2018-10-10 15:13:40.469708+0800 Visit_Thread[5027:297386] 1+++<NSThread: 0x60400027e980>{number = 3, name = (null)}
2018-10-10 15:13:40.469735+0800 Visit_Thread[5027:297367] 3___<NSThread: 0x600000670640>{number = 6, name = (null)}
2018-10-10 15:13:40.469735+0800 Visit_Thread[5027:297385] 2+++<NSThread: 0x600000670880>{number = 7, name = (null)}
2018-10-10 15:13:41.468790+0800 Visit_Thread[5027:297366] 3+++<NSThread: 0x604000465dc0>{number = 8, name = (null)}
2018-10-10 15:13:41.475239+0800 Visit_Thread[5027:297386] 1+++<NSThread: 0x60400027e980>{number = 3, name = (null)}
2018-10-10 15:13:42.475216+0800 Visit_Thread[5027:297367] 3___<NSThread: 0x600000670640>{number = 6, name = (null)}
2018-10-10 15:13:42.475216+0800 Visit_Thread[5027:297365] 1___<NSThread: 0x604000465b80>{number = 4, name = (null)}
2018-10-10 15:13:42.475227+0800 Visit_Thread[5027:297364] 2___<NSThread: 0x604000465c40>{number = 5, name = (null)}
2018-10-10 15:13:42.475260+0800 Visit_Thread[5027:297385] 2+++<NSThread: 0x600000670880>{number = 7, name = (null)}
2018-10-10 15:13:44.469294+0800 Visit_Thread[5027:297366] 3+++<NSThread: 0x604000465dc0>{number = 8, name = (null)}
2018-10-10 15:13:44.479592+0800 Visit_Thread[5027:297364] 2___<NSThread: 0x604000465c40>{number = 5, name = (null)}
2018-10-10 15:13:44.479596+0800 Visit_Thread[5027:297367] 3___<NSThread: 0x600000670640>{number = 6, name = (null)}
2018-10-10 15:13:44.479592+0800 Visit_Thread[5027:297365] 1___<NSThread: 0x604000465b80>{number = 4, name = (null)}
2018-10-10 15:13:44.479641+0800 Visit_Thread[5027:297385] 2+++<NSThread: 0x600000670880>{number = 7, name = (null)}
2018-10-10 15:13:47.471226+0800 Visit_Thread[5027:297366] 3+++<NSThread: 0x604000465dc0>{number = 8, name = (null)}
NSOperation的暂停、恢复和取消
- (IBAction)start:(id)sender {
NSLog(@"start");
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
_queue = queue;
queue.maxConcurrentOperationCount = 1;
[queue addOperationWithBlock:^{
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1___%@",[NSThread currentThread]);
}
}];
[queue addOperationWithBlock:^{
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2___%@",[NSThread currentThread]);
}
}];
[queue addOperationWithBlock:^{
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3___%@",[NSThread currentThread]);
}
}];
[queue addOperationWithBlock:^{
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"4___%@",[NSThread currentThread]);
}
}];
NSLog(@"end");
}
- (IBAction)suspend:(id)sender {
NSLog(@"暂停");
//不能暂停正在处于执行状态的任务
[_queue setSuspended:YES];
}
- (IBAction)goOn:(id)sender {
NSLog(@"继续");
[_queue setSuspended:NO];
}
- (IBAction)cancel:(id)sender {
NSLog(@"取消");
//取消之后,不能恢复
[_queue cancelAllOperations];
}
打印结果:
2018-10-10 17:05:36.939569+0800 Visit_Thread[6591:388486] start
2018-10-10 17:05:36.940215+0800 Visit_Thread[6591:388486] end
2018-10-10 17:05:38.945240+0800 Visit_Thread[6591:388556] 1___<NSThread: 0x604000462f00>{number = 3, name = (null)}
2018-10-10 17:05:40.948462+0800 Visit_Thread[6591:388556] 1___<NSThread: 0x604000462f00>{number = 3, name = (null)}
2018-10-10 17:05:41.736979+0800 Visit_Thread[6591:388486] 暂停
2018-10-10 17:05:42.948923+0800 Visit_Thread[6591:388556] 1___<NSThread: 0x604000462f00>{number = 3, name = (null)}
2018-10-10 17:06:01.016564+0800 Visit_Thread[6591:388486] 继续
2018-10-10 17:06:03.022025+0800 Visit_Thread[6591:388809] 2___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:05.027504+0800 Visit_Thread[6591:388809] 2___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:06.148510+0800 Visit_Thread[6591:388486] 暂停
2018-10-10 17:06:07.028798+0800 Visit_Thread[6591:388809] 2___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:09.031857+0800 Visit_Thread[6591:388809] 2___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:11.032833+0800 Visit_Thread[6591:388809] 2___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:14.879380+0800 Visit_Thread[6591:388486] 继续
2018-10-10 17:06:16.882917+0800 Visit_Thread[6591:388809] 3___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:18.885551+0800 Visit_Thread[6591:388809] 3___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:20.889610+0800 Visit_Thread[6591:388809] 3___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:22.890000+0800 Visit_Thread[6591:388809] 3___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:24.893687+0800 Visit_Thread[6591:388809] 3___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:26.896813+0800 Visit_Thread[6591:388893] 4___<NSThread: 0x60400026e640>{number = 5, name = (null)}
2018-10-10 17:06:28.898334+0800 Visit_Thread[6591:388893] 4___<NSThread: 0x60400026e640>{number = 5, name = (null)}
2018-10-10 17:06:30.898909+0800 Visit_Thread[6591:388893] 4___<NSThread: 0x60400026e640>{number = 5, name = (null)}
2018-10-10 17:06:32.212768+0800 Visit_Thread[6591:388486] 取消
结合打印结果可知:
maxConcurrentOperationCount
为1时串行执行
串行执行不等于只开一条线程
不能暂停正在处于执行状态的任务
同样的,也不能取消正在执行的任务,必须要等当前任务执行完毕才能取消
任务取消之后,便不能恢复
继承NSOperation
#import <UIKit/UIKit.h>
@interface DownloadImgOperation : NSOperation
- (instancetype)initWithURL:(NSURL *)url imageView:(UIImageView *)imageView;
@end
#import "DownloadImgOperation.h"
@interface DownloadImgOperation()
@property (strong, nonatomic) NSURL *url;
@property (strong, nonatomic) UIImageView *imageView;
@end
@implementation DownloadImgOperation
- (void)main {//重写main方法
NSData *data = [[NSData alloc]initWithContentsOfURL:self.url];
UIImage *image = [[UIImage alloc]initWithData:data];
if (image != nil) {
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}else {
NSLog(@"download error");
}
}
- (instancetype)initWithURL:(NSURL *)url imageView:(UIImageView *)imageView {
if (self = [super init]) {
self.imageView = imageView;
self.url = url;
}
return self;
}
- (void)updateUI:(UIImage *)image {
self.imageView.image =image;
}
@end
如果是在自定义Operation中的main方法中有耗时操作,那么需要特别处理:
- (void)main {//重写main方法
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1___%@",[NSThread currentThread]);
}
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2___%@",[NSThread currentThread]);
}
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3___%@",[NSThread currentThread]);
}
}
调用注意点:
1、暂定功能不起作用,因为暂停是针对多个Operation
的,开始时只有一个,暂停时需要等这个Operation
执行完毕,所以没有意义,取消也是如此。那么继续也便没有意义。
2、但是可以实现通过改进,来实现取消功能(在main
方法中做更改):
- (IBAction)start:(id)sender {
NSLog(@"start");
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
_queue = queue;
queue.maxConcurrentOperationCount = 1;
DownloadImgOperation *operation = [[DownloadImgOperation alloc]init];
[_queue addOperation:operation];
NSLog(@"end");
}
- (IBAction)cancel:(id)sender {
NSLog(@"取消");
[_queue cancelAllOperations];
}
更改main
方法:
- (void)main {//重写main方法
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:2];
//虽然在此处可以做到精确控制,但是如果循环次数太多,每次都需要做判断,所以不建议这样使用
// if(self.isCancelled) return;
NSLog(@"1___%@",[NSThread currentThread]);
}
if(self.isCancelled) return;
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2___%@",[NSThread currentThread]);
}
if(self.isCancelled) return;
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3___%@",[NSThread currentThread]);
}
}
设置NSOperation的依赖与监听
- (IBAction)start:(id)sender {
NSLog(@"start");
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSOperationQueue *queue2 = [[NSOperationQueue alloc]init];
NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:1];
NSLog(@"1___%@",[NSThread currentThread]);
}
}];
NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:1];
NSLog(@"2___%@",[NSThread currentThread]);
}
}];
NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 5; i++) {
[NSThread sleepForTimeInterval:1];
NSLog(@"3___%@",[NSThread currentThread]);
}
}];
NSBlockOperation *task4 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:1];
NSLog(@"4___%@",[NSThread currentThread]);
}
}];
//设置依赖:
//
[task2 addDependency:task1];//必须等task1的任务执行完毕task2才能执行
[task3 addDependency:task2];//必须等task2的任务执行完毕task3才能执行
task1.completionBlock = ^ {
NSLog(@"task1执行完毕了————%@",[NSThread currentThread]);
};
[queue addOperation:task1];
[queue2 addOperation:task2];
[queue2 addOperation:task3];
[queue addOperation:task4];
NSLog(@"end");
}
打印结果:
2018-10-10 18:25:08.234783+0800 Visit_Thread[7925:466651] start
2018-10-10 18:25:08.235548+0800 Visit_Thread[7925:466651] end
2018-10-10 18:25:09.238803+0800 Visit_Thread[7925:466803] 4___<NSThread: 0x600000478880>{number = 4, name = (null)}
2018-10-10 18:25:09.238801+0800 Visit_Thread[7925:466707] 1___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:10.242784+0800 Visit_Thread[7925:466803] 4___<NSThread: 0x600000478880>{number = 4, name = (null)}
2018-10-10 18:25:10.242784+0800 Visit_Thread[7925:466707] 1___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:11.247918+0800 Visit_Thread[7925:466803] 4___<NSThread: 0x600000478880>{number = 4, name = (null)}
2018-10-10 18:25:11.247918+0800 Visit_Thread[7925:466707] 1___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:11.248278+0800 Visit_Thread[7925:466707] task1执行完毕了————<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:12.248466+0800 Visit_Thread[7925:466810] 2___<NSThread: 0x60000047f3c0>{number = 5, name = (null)}
2018-10-10 18:25:13.252236+0800 Visit_Thread[7925:466810] 2___<NSThread: 0x60000047f3c0>{number = 5, name = (null)}
2018-10-10 18:25:14.256300+0800 Visit_Thread[7925:466810] 2___<NSThread: 0x60000047f3c0>{number = 5, name = (null)}
2018-10-10 18:25:15.261807+0800 Visit_Thread[7925:466810] 2___<NSThread: 0x60000047f3c0>{number = 5, name = (null)}
2018-10-10 18:25:16.267055+0800 Visit_Thread[7925:466810] 2___<NSThread: 0x60000047f3c0>{number = 5, name = (null)}
2018-10-10 18:25:17.267466+0800 Visit_Thread[7925:466707] 3___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:18.272417+0800 Visit_Thread[7925:466707] 3___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:19.275128+0800 Visit_Thread[7925:466707] 3___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:20.280244+0800 Visit_Thread[7925:466707] 3___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:21.281868+0800 Visit_Thread[7925:466707] 3___<NSThread: 0x600000476900>{number = 3, name = (null)}
NSOperation的线程间的通信
1、方式1
- (IBAction)start:(id)sender {
NSLog(@"start");
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// [queue addOperationWithBlock:^{
// //coding
// }];
__block UIImage *img ;
NSBlockOperation *task = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"http://c.hiphotos.baidu.com/image/h%3D300/sign=c635d3753efa828bce239be3cd1f41cd/0eb30f2442a7d933b29eb303a04bd11373f0018f.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
img = [UIImage imageWithData:data];
}];
task.completionBlock = ^ {
NSLog(@"task1执行完毕了————%@",[NSThread currentThread]);
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
self.imgView.image = img;
}];
};
[queue addOperation:task];
NSLog(@"end");
}
2、方式2
- (IBAction)start:(id)sender {
NSLog(@"start");
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperationWithBlock:^{
//coding
NSLog(@"%@",[NSThread currentThread]);
}];
__block UIImage *img ;
NSBlockOperation *task = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"http://c.hiphotos.baidu.com/image/h%3D300/sign=c635d3753efa828bce239be3cd1f41cd/0eb30f2442a7d933b29eb303a04bd11373f0018f.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [UIImage imageWithData:data];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imgView.image = img;
}];
}];
[queue addOperation:task];
NSLog(@"end");
}
练习:将2张图片合成一张图片并展示
- (IBAction)start:(id)sender {
NSLog(@"start");
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
__block UIImage *img1 ;
NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"http://c.hiphotos.baidu.com/image/h%3D300/sign=c635d3753efa828bce239be3cd1f41cd/0eb30f2442a7d933b29eb303a04bd11373f0018f.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
img1 = [UIImage imageWithData:data];
}];
__block UIImage *img2 ;
NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/h%3D300/sign=b48b76f776899e51678e3c1472a6d990/e824b899a9014c08ef778daf077b02087bf4f468.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
img2 = [UIImage imageWithData:data];
}];
NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
[img1 drawInRect:CGRectMake(0, 0, 200, 100)];
[img2 drawInRect:CGRectMake(0, 100, 200, 100)];
UIImage *combinImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
self.imgView.image = combinImg;
}];
}];
[task3 addDependency:task1];
[task3 addDependency:task2];
[queue addOperation:task1];
[queue addOperation:task2];
[queue addOperation:task3];
NSLog(@"end");
}