iOS学习笔记——多线程

来源:互联网 发布:ae cs6 mac 破解 编辑:程序博客网 时间:2024/05/22 13:37

iOS的多线程,分为由以下三种实现方式: 
     1、 Thread
     2、 Cocoa operations
     3,、Grand Central Dispatch (GCD) 
这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的
(本文参考自网络)
一、NSThread
    优点:NSThread 比其他两个轻量级
     缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销 
     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: 是一样的。
     
          线程间通讯:
          [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
          performSelectorOnMainThread是NSObject的方法,除了可以更新主线程的数据外,还可以更新其他线程的比如:
          用:performSelector:onThread:withObject:waitUntilDone:  

二、NSOperation:

      Cocoa operation 相关的类是 NSOperation ,NSOperationQueue。NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。 

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

      NSOpera
    (1)并发执行时,需要重载如下4个方法
             - (void)start                        //执行任务主函数,线程运行的入口函数
             - (BOOL) isConcurrent      //是否允许并发,返回YES,允许并发,返回NO不允许。默认返回NO
             -  (BOOL)isExecuting
             -  (BOOL)isFinished            //是否已经完成,这个必须要重载,不然放在放在NSOperationQueue里的NSOpertaion不能正常释放。

     使用方法:
    NSOperationQueue *queue = [[NSOperationQueue alloc ] init];
     [queue addOperation:testNSoperation];
     它会自动调用TestNSOperation里的start函数,如果需要多个NSOperation,你需要设置queue的一些属性,如果多个NSOperation之间有依赖关系也可以设置。 
    (2)非并发执行,只需要重载这个main方法就可以了。 
           -(void)main

 
三、 GCD


          dispatch_async(dispatch_queue_t queue,dispatch_block_t block);
          async表明异步运行,block代表的是你要做的事情,queue则是你把任务交给谁来处理了.

          之所以程序中会用到多线程是因为程序往往会需要读取数据,然后更新UI.为了良好的用户体验,读取数据的操作会倾向于在后台运行,这样以避免阻塞主线程.GCD里就有三种queue来处理。
        1. Main queue:
               顾名思义,运行在主线程,由dispatch_get_main_queue获得.和ui相关的就要使用MainQueue.
          2.Serial quque(private dispatch queue)
               每次运行一个任务,可以添加多个,执行次序FIFO. 通常是指程序员生成的.
          3. Concurrent queue(globaldispatch queue):
               可以同时运行多个任务,每个任务的启动时间是按照加入queue的顺序,结束的顺序依赖各自的任务.使用dispatch_get_global_queue获得.
               所以我们可以大致了解使用GCD的框架:
               dispatch_async(getDataQueue,^{         //获取数据,获得一组后,刷新UI.
                     dispatch_aysnc(mainQueue, ^{         //UI的更新需在主线程中进行
                    };
               });

总结:     
          Thread 是这三种范式里面相对轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程之间的同步。线程共享同一应用程序的部分内存空间, 它们拥有对数据相同的访问权限。你得协调多个线程对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。在 iOS 中我们可以使用多种形式的 thread:
       Cocoa threads: 使用NSThread 或直接从 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程。如果你选择thread来实现多线程,那么 NSThread 就是官方推荐优先选用的方式。
       Cocoa operations是基于 Obective-C实现的,类 NSOperation 以面向对象的方式封装了用户需要执行的操作,我们只要聚焦于我们需要做的事情,而不必太操心线程的管理,同步等事情,因为NSOperation已经为我 们封装了这些事情。 NSOperation 是一个抽象基类,我们必须使用它的子类。iOS 提供了两种默认实现:NSInvocationOperation 和 NSBlockOperation。
       Grand Central Dispatch (GCD): iOS4 才开始支持,它提供了一些新的特性,以及运行库来支持多核并行编程,它的关注点更高:如何在多个 cpu 上提升效率。

       最后,既然说道多线程的开发,难免会在多线程之间进行通讯;
         利用NSObject的一些类方法,可以轻松搞定。

         在应用程序主线程中做事情:
       - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
       - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array

       在指定线程中做事情:
       - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait
       - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array

       在当前线程中做事情:

      - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay performSelector:withObject:afterDelay:inModes

       取消发送给当前线程的某个消息
          cancelPreviousPerformRequestsWithTarget:
          cancelPreviousPerformRequestsWithTarget:selector:object:

         如在我们在某个线程中下载数据,下载完成之后要通知主线程中更新界面等等,可以使用如下接口:- (void)myThreadMainMethod
          {
              NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
              // to do something in your thread job
              ...
              [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];
              [pool release];
          }

0 0
原创粉丝点击