NSOperation是OC中多线程技术的一种,是对GCD的OC包装.它包含队列(NSOperationQueue)和操作(NSOperation)两个基本要素.
NSInvocationOperation,NSBlockOperation
- NSInvocationOperation
先看看这两个。
//NSInvocationOperation 没用NSOperationQueue,在主线程调用执行
-(void)demo
{
NSLog(@"---begin");
NSInvocationOperation *operation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];
[operation start];
NSLog(@"---end");
}
-(void)test
{
[NSThread sleepForTimeInterval:4];
for (int i=0; i<3; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}
编译结果如下:
- NSBlockOperation
NSLog(@"---begin");
NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:4];
for (int i=0; i<3; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}];
[blockOp start];
NSLog(@"---end");
编译结果如下:
从上面两个编译结果可以看出,没有使用NSOperationQueue时,要调用start开始执行,没有开启新的线程,所以---end需要等其执行完再打印。
NSBlockOperation还有一种使用方法addExecutionBlock:
可以添加更多操作。
NSLog(@"---begin");
//主线程中执行
NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
for (int i=0; i<3; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}];
//主线程和其他线程中执行
[blockOp addExecutionBlock:^{
[NSThread sleepForTimeInterval:2];
for (int i=3; i<6; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}];
[blockOp addExecutionBlock:^{
[NSThread sleepForTimeInterval:3];
for (int i=6; i<9; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}];
[blockOp start];
NSLog(@"---end");
编译结果如下:
从我这里的结果来说blockOperationWithBlock里的任务是在主线程执行的,addExecutionBlock里的任务是在主线程和其他线程执行的。而且这里NSBlockOperation时阻塞了主线程的,NSBlockOperation的任务执行完之后才打印---end,NSOperation的start方法默认是同步执行任务.
NSOperationQueue
接下来就看看这个了。
- [queue addOperation:invOp]
-(void)demo3
{
NSLog(@"---begin");
//队列
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount=-1;//最大并发数 1即为串行 默认-1并行
//任务
NSInvocationOperation *invOp=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];
NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:2];
for (int i=3; i<6; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}];
[queue addOperation:invOp];
[queue addOperation:blockOp];
NSLog(@"---end");
}
-(void)test
{
[NSThread sleepForTimeInterval:2];
for (int i=0; i<3; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}
编译结果如下:
使用NSOperationQueue时,设置
maxConcurrentOperationCount
最大并发数,默认-1并行,1即为串行。
- addOperationWithBlock
NSLog(@"---begin");
//队列
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
//任务
[queue addOperationWithBlock:^{
[self test];
}];
[queue addOperationWithBlock:^{
[NSThread sleepForTimeInterval:2];
for (int i=3; i<6; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}];
NSLog(@"---end");
效果一样,使用方法不一样而已。
- 添加依赖和监听addDependency,completionBlock
NSLog(@"---begin");
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
for (int i=0; i<3; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}];
NSBlockOperation *blockOp1=[NSBlockOperation blockOperationWithBlock:^{
for (int i=3; i<6; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}];
NSBlockOperation *blockOp2=[NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:2];
for (int i=6; i<9; i++) {
NSLog(@"---%d---%@",i,[NSThread currentThread]);
}
}];
//blockOp 依赖于blockOp1,即等blockOp1 执行完再执行 blockOp
[blockOp addDependency:blockOp1];
[queue addOperation:blockOp];
[queue addOperation:blockOp1];
[queue addOperation:blockOp2];
blockOp.completionBlock=^{
NSLog(@"---blockOp over");
};
NSLog(@"---end");
编译结果如下:
blockOp 依赖于blockOp1,等blockOp1里的任务执行完再执行blockOp的任务,blockOp执行完completionBlock回调打印---blockOp over. blockOp1和blockOp2执行顺序先后是不确定的(异步)。
- NSOperationQueue的取消
-(void)demo6
{
NSLog(@"---h begin");
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount=1;
NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
for (int i=0; i<3; i++) {
NSLog(@"---h %d---%@",i,[NSThread currentThread]);
}
}];
NSBlockOperation *blockOp1=[NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:1];
for (int i=3; i<6; i++) {
NSLog(@"---h %d---%@",i,[NSThread currentThread]);
}
}];
NSBlockOperation *blockOp2=[NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:3];
for (int i=6; i<9; i++) {
NSLog(@"---h %d---%@",i,[NSThread currentThread]);
}
}];
NSBlockOperation *blockOp3=[NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:4];
for (int i=9; i<12; i++) {
NSLog(@"---h %d---%@",i,[NSThread currentThread]);
}
}];
[queue addOperation:blockOp];
[queue addOperation:blockOp1];
[queue addOperation:blockOp2];
[queue addOperation:blockOp3];
self.blockOperation=blockOp3;
self.queue=queue;
NSLog(@"---h end");
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//[self.blockOperation cancel];
[self.queue cancelAllOperations];
}
编译结果如下:
- NSOperationQueue的暂停恢复
-(void)demo6
{
NSLog(@"---h begin");
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount=1;
NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
for (int i=0; i<3; i++) {
NSLog(@"---h %d---%@",i,[NSThread currentThread]);
}
}];
NSBlockOperation *blockOp1=[NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:1];
for (int i=3; i<6; i++) {
NSLog(@"---h %d---%@",i,[NSThread currentThread]);
}
}];
NSBlockOperation *blockOp2=[NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:3];
for (int i=6; i<9; i++) {
NSLog(@"---h %d---%@",i,[NSThread currentThread]);
}
}];
NSBlockOperation *blockOp3=[NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:4];
for (int i=9; i<12; i++) {
NSLog(@"---h %d---%@",i,[NSThread currentThread]);
}
}];
[queue addOperation:blockOp];
[queue addOperation:blockOp1];
[queue addOperation:blockOp2];
[queue addOperation:blockOp3];
self.blockOperation=blockOp3;
self.queue=queue;
NSLog(@"---h end");
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
self.queue.suspended=!self.queue.suspended;
if (self.queue.suspended) {
NSLog(@"---h暂停");
}else
{
NSLog(@"---h恢复");
}
}
编译结果如下:
![NSOperationQueue的暂停恢复.png](http://upload-images.jianshu.io/upload_images/3339381-4b450b2aad3becbf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
NSOperationQueue有个suspended属性,当为YES的时候暂停,为NO时执行。当我点击屏幕时打印暂停,打印结果可以看出并没有马上暂停,它会把正在执行的任务完成才暂停。
---------------------个人对NSOperation的总结暂时就这么多吧。