无标题
Posted 亚布./
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无标题相关的知识,希望对你有一定的参考价值。
一.NSOperation
把操作加入到队列。NSOperation是一个抽象的类,需要初始化子类去实现。
三种方式使用它:1.使用子类 NSInvocationOperation;2、使用子类 NSBlockOperation; 3、自定义继承自 NSOperation 的子类,通过实现内部相应的方法来封装操作。
二、NSInvocationOperation
//创建事务
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(handlerInvocaton:) object:@"ico"];
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//将任务加入到队列
[queue addOperation:op];
如果不加入指定队列,直接调用NSInvocationOperation父类NSOperation的start方法,就没有开启新的线程,任务都是在当前线程中执行的。
//创建事务
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(handlerInvocaton:) object:@"ico"];
//并没有开启新的线程,任务在当前线程中执行
[op start];
NSOperationQueue提供了主队列和自定义队里两种队列,其中自定义队列中包含了串行和并发两种不同的功能。
- 主队列:通过
[NSOperationQueue mainQueue]
方式获取,凡是添加到主队列中的任务都会放到主线程中执行。 - 自定义队列:通过
[[NSOperationQueue alloc] init]
方式创建一个队列,凡是添加到自定义队列中的任务会自动放到子线程中执行。
三、NSBlockOperation
NSBlockOperation
类是NSOperation的一个具体子类,它充当一个或多个块对象的包装,函数式编程思想,代码可读性更强。该类为已经使用操作队列且不希望创建分派队列的应用程序提供了面向对象的包装器。您还可以使用块操作来利用操作依赖、KVO通知和其他可能与调度队列不可用的特性。
//创建block任务
NSBlockOperation *opBlock = [NSBlockOperation blockOperationWithBlock:^
NSLog(@"%@", [NSThread currentThread]);
];
//添加代码执行块
[opBlock addExecutionBlock:^
NSLog(@"这是一个执行代码块 --- %@", [NSThread currentThread]);
];
//设置监听
opBlock.completionBlock = ^
NSLog(@"完成了");
;
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//添加到队列
[queue addOperation:opBlock];
NSLog(@"事务添加进了NSOperationQueue"); //任务1
打印结果:
2022-01-25 04:53:37.131818+0800 StringCopyText[26206:863102] 事务添加进了NSOperationQueue
2022-01-25 04:53:37.131912+0800 StringCopyText[26206:863150] 这是一个执行代码块 --- <NSThread: 0x600002f7a080>number = 4, name = (null)
2022-01-25 04:53:37.131910+0800 StringCopyText[26206:863149] <NSThread: 0x600002f06740>number = 6, name = (null)
2022-01-25 04:53:37.132124+0800 StringCopyText[26206:863150] 完成了
为什么会先执行【任务1】处的代码?因为【任务1】是在主线程执行的,而我们的block任务添加到自定义队列,执行也就在子线程执行了。
如果NSBlockOperation单独使用时(直接调用start方法),就没有开启新的线程,任务的执行都是在当前线程中执行的。
在NSBlockOperation类中还提供一个addExecutionBlock方法,这个方法可以添加一个代码执行块,当需要执行NSBlockOperation对象时,该对象将其所有块提交给默认优先级的并发调度队列。然后对象等待,直到所有的块完成执行。当最后一个块完成执行时,操作对象将自己标记为已完成。
因此,我们可以使用块操作来跟踪一组执行的块,这与使用线程连接来合并来自多个线程的结果非常相似。不同之处在于,由于块操作本身在单独的线程上运行,所以应用程序的其他线程可以在等待块操作完成的同时继续工作。需要说明的一点是,如果添加的任务较多的话,这些操作(包括 blockOperationWithBlock 中的操作)可能在不同的线程中并发执行,这是由系统决定的。
四、线程间通信
NSOperation线程间的通信十分简单
-(void)threadCommunication
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^
for (int i = 0; i < 4; i++)
[NSThread sleepForTimeInterval:2];
NSLog(@"子线程--%@", [NSThread currentThread]);
[[NSOperationQueue mainQueue] addOperationWithBlock:^
for (int i = 0; i < 2; i++)
[NSThread sleepForTimeInterval:2];
NSLog(@"主线程--%@", [NSThread currentThread]);
];
];
[queue addOperation:operation];
打印结果:
2020-03-19 21:48:12.051256+0800 ThreadDemo[48922:12893188] 子线程--<NSThread: 0x600000b5fa80>number = 6, name = (null)
2020-03-19 21:48:14.056107+0800 ThreadDemo[48922:12893188] 子线程--<NSThread: 0x600000b5fa80>number = 6, name = (null)
2020-03-19 21:48:16.059279+0800 ThreadDemo[48922:12893188] 子线程--<NSThread: 0x600000b5fa80>number = 6, name = (null)
2020-03-19 21:48:18.062773+0800 ThreadDemo[48922:12893188] 子线程--<NSThread: 0x600000b5fa80>number = 6, name = (null)
2020-03-19 21:48:20.064401+0800 ThreadDemo[48922:12893108] 主线程--<NSThread: 0x600000bd2d00>number = 1, name = main
2020-03-19 21:48:22.065409+0800 ThreadDemo[48922:12893108] 主线程--<NSThread: 0x600000bd2d00>number = 1, name = main
五、NSOperation 操作依赖
NSOperation提供了三个方法为任务之间设置依赖关系
-(void)addDependency:(NSOperation *)op;
添加依赖,使当前操作依赖于操作 op 的完成。-(void)removeDependency:(NSOperation *)op;
移除依赖,取消当前操作对操作 op 的依赖。NSArray<NSOperation *> *dependencies;
在当前操作开始执行之前完成执行的所有操作对象数组。
maxConcurrentOperationCount设置最大并发数。
- 默认情况下
maxConcurrentOperationCount
的值是-1,并不做限制,可以并发执行,如上面提到的NSBlockOperation添加多个任务块。 maxConcurrentOperationCount
的值为1时,同步执行。maxConcurrentOperationCount
的值大于1时,并发执行。maxConcurrentOperationCount
的值并不是表示并发执行的线程数量,而是在一个队列中能够同时执行的任务的数量。
已经被调度的任务是无法挂起(suspended)的。正在执行的任务已经从队列里调度出来,加入到线程里面去执行了。
已经取消的任务,再次点击继续,发现没有任务调度了,下次就需要重新添加任务。
以上是关于无标题的主要内容,如果未能解决你的问题,请参考以下文章
Synapse Analytics 无服务器池 >> 每天早上从外部表读取数据时都会出现问题