NSThread,NSInvocationOperation,NSBlockOperation,GCD解析

来源:互联网 发布:淘宝店宝贝描述 编辑:程序博客网 时间:2024/03/29 15:24

iOS有三种多线程编程的技术,分别是:

(一) NSThread

(二)Cocoa NSOperation

(三)GCD(全称:Grand Central Dispatch)

  这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的。


三种方式介绍:

1)NSThread

      在处理机制上,需要开发者负责手动管理Thread的生命周期,包括子线程与主线程之间的同步等。线程共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。你得协调多个线程对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。

2)NSOperation

      可以认为NSOperationQueue就是一个线程管理器,通过addOperation方法,我们可以一次性把多个线程添加到队列中。同时,NSOperationQueue允许通过setMaxConcurrentOperationCount方法设置队列并行执行的线程数量。

3)GCD

      GCD是Apple开发的一个多核编程的解决方法。该方法在Mac OS X 10.6雪豹中首次推出,并随后被引入到了iOS4.0中。GCD是一个替代诸如NSThread,NSOperationQueue,NSInvocationOperation等技术的很高效和强大的技术。


三种方式的优缺点介绍:

1)NSThread:

优点:NSThread 比其他两个轻量级

缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的枷锁会有一定的系统开销。

2)Cocoa NSOperation

优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。

Cocoa operation相关的类是 NSOperation, NSOperationQueue.

              NSOperation是个抽象类,使用它必须使用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation.

              NSOperationQueue是线程队列,里面存放需要执行的线程。  创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。

3)GCD

优点:GCD比之thread更简单易用。并且处理效率很高。GCD自动根据系统负载来增减线程数量,这就减少了上下文切换以及增加了计算效率。


三种方法的方法介绍:

1)NSThread:

创建方式主要有两种:

[NSThread detachNewThreadSelector:@selector(myThreadMainMethod:) toTarget:self withObject:nil];

NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:@selector(myThreadMainMethod:)
object:nil];
[myThread start]; //启动线程

这两种方式的区别是:前一种一调用就会立即创建一个线程来做事情;而后一种虽然你 alloc 了也 init了,但是要直到我们手动调用 start 启动线程时才会真正去创建线程。这种延迟实现思想在很多跟资源相关的地方都有用到。后一种方式我们还可以在启动线程之前,对线程进行配置,比如设置 stack 大小,线程优先级。
此外还有一种间接的方式:利用NSObject的方法
performSelectorInBackground:withObject: 来创建一个线程:
[myObj performSelectorInBackground:@selector(myThreadMainMethod) withObject:nil]; //在后台运行某一个方法
其效果与 NSThread 的 detachNewThreadSelector:toTarget:withObject: 是一样的。

2)NSOperationQueue:

1> 使用步骤:

    1) 实例化操作

      _queue = [[NSOperationQueue alloc] init];

     a) NSInvocationOperation

       NSInvocationQperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(opAction) object:nil];

      // 如果使用start,会在当前线程启动操作

       [op1 start];

      //一旦将操作添加到操作队列,操作就会启动

       [_queue addOperation:op1];


       b) NSBlockOperation

       #pragma mark  -模仿下载网络图像

       - (IBAction)operationDemo3:(id)sender

       {

         //1.下载

          NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{

                NSLog(@"下载%@",[NSThread currendThread]);

         }];

         // 2.滤镜

        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{

             NSLog(@"下载%@",[NSThread currendThread]);

       }];

           //3.显示

          NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{

               NSLog(@"更新UI%@",[NSThread currendThread]);

           }];

         

          //添加操作之间的依赖关系,所谓“依赖”关系,就是等待前一个任务完成后,后一个任务才能启动

          //依赖关系可以跨线程队列实现

         //提示:在指定依赖关系时,注意不要循环依赖,否则不工作。

         [op2 addDepandency:op1];

         [op3 addDependency:op2];

         [_queue addOperation:op1];

         [_queue addOperation:op2]; 

         [[NSOperationQueue mainQueue] addOperation:op3];

       }

 

    2) 将操作添加到队列NSOperationQueue即可启动多线程执行

         [_queue addOperation:op1];

         [_queue addOperation:op2];

 2> 更新UI使用主线程队列

        //两方式

        [[NSOperationQueue mainQueue] addOperation:^{


          [[NSOperationQueue mainQueue] addOperation:op3];

        }];

 

 3> 操作队列的setMaxConcurrentOperationCount

    可以设置同时并发的线程数量!

   [_queue setMacConcurrentOperationCount:2];

    提示:此功能仅有NSOperation有!

 

 4> 使用addDependency可以设置任务的执行先后顺序,同时可以跨操作队列指定依赖关系

   [op2 addDependency:op1];

      [op3 addDependency:op2];

      [op1 addDepandency:op3];

    提示:在指定依赖关系时,注意不要循环依赖,否则不工作。



0 0
原创粉丝点击