码迷,mamicode.com
首页 > 移动开发 > 详细

iOS多线程编程

时间:2016-08-04 23:07:50      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:

iOS多线程编程

 

1. 进程,线程, 任务

   进程:一个程序在运行时,系统会为其分配一个进程,用以管理他的一些资源。

   线程:进程内所包含的一个或多个执行单元称为线程,线程一般情况下不持有资源,但可以使用其所在进程的资源。

   任务:进程或线程中要做的事情。

 

   在引入线程的操作系统中,通常把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位。

    线程比进程更小,对其调度的开销小,能够提高系统内多个任务的并发执行程度。

    一个程序至少有一个进程,一个进程至少有一个线程.一个程序就是一个进程,而一个程序中的多个任务则被称为线程。

    线程只能归属于一个进程并且它只能访问该进程所拥有的资源。当操作系统创建一个进程后,该进程会自动申请一个名为主线程或首要线程的线程。应用程序(application)是由一个或多个相互协作的进程组成的。

    多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

    

2. iOS多线程编程技术

    共有三种(实际上是四种,还有Pthreads,C语言框架)

    > NSThread

    > NSOperation

    > GCD (Grand Central Dispatch)

    从上到下,封装度从低到高,封装度越高使用越简单,也是官方推荐使用。

    

    三种方式的比较:

    NSThread:  相对于另外两种是比较轻量级的。此种方式是经官方封装后的,是完全面向对象的,所以可以直接操控线程对象,非常直观方便。但是需要自己管理线程的生命周期,线程同步,而且线程同步对数据的加锁会有一定的系统开销。使用比较简单,但不够智能,在一些简单的场景才使用。

    NSOperation: 完全面向对象的。相关的主要类有 NSOperation(任务) 和 NSOperationQueue(任务队列),其中NSOperationQueue 在iOS4引入GCD后,其内部用GCD实现的。此种方式下不需要关心线程管理,数据同步的操作。隐藏了许多复杂的代码,提供了简单的API。

    GCD : 是苹果为多核并行运算提出的解决方案,会自动合理的利用更多的CPU内核(如双核,四核)。此种方式也能自动管理线程的生命周期(创建线程,调度任务,销毁线程),不需要自己管理,只需要告诉其要做的操作是什么就可以。虽然也使用c语言,但因为使用了block, 使用也很方便,灵活。在GCD中也有“任务”,“队列”的概念。

  

 

一、NSThread  ===========================================

1. 使用NSThread创建并管理线程

   > 创建线程

      方式一:实例方法

      [NSThread alloc] initWithTarget: selector : object:]

      参数一:线程操作消息的接收者 self

      参数二:选择器方法,线程操作的方法,此方法只能带一个参数,而且不能有返回值

      参数三:线程操作方法所带的参数

      使用该方式创建的线程不会自动启动,需调用线程方法:

      [thread start]  // 开始启动并执行线程

      方式二:类方法

      [NSThread detachNewThreadSelector: toTarget: withObject: ]

      参数同上同名参数;

      此方法创建的线程会自动启动执行,无需手动开启。

    > 线程方法

       //取消线程

       - (void)cancel;

       //启动线程

       - (void)start;

       //设置/获取某个线程的状态

       @property (readonly, getter=isExecuting) BOOL executing;

       @property (readonly, getter=isFinished) BOOL finished;

       @property (readonly, getter=isCancelled) BOOL cancelled;

       //设置和获取线程名字

       -(void)setName:(NSString *)n;

       -(NSString *)name;

       //获取当前线程

       + (NSThread *)currentThread;

       //获取主线程

       + (NSThread *)mainThread;

       //使当前线程暂停一段时间,或者暂停到某个时刻

       + (void)sleepForTimeInterval:(NSTimeInterval)time;

       + (void)sleepUntilDate:(NSDate *)date;

       // 设置线程优先级

       + (BOOL)setThreadPriority:(double)p;

      > 线程间的通信

       在非主线程上绝对不能去访问UI, 必须在主线程上更新

       [self performSelectorOnMainThread:@selector(updateUI:) withObject:data waitUntilDone:YES];

       线程与线程间可进行数据通讯

       [self performSelector:@selector(senddata:) onThread:thread2 withObject:obj waitUntilDone:YES]

      > 线程同步

        多个线程访问同一共享资源时,为保证数据资源的准确性,需对资源进行加锁,是在一个时刻上只有一个线程访问共享资源,其他线程则排队等待。

         NSLock 锁

         [[NSLock alloc] init]

         [theLock lock];

         …..要访问的共享资源

         [theLock unlock];

      

二、NSOperation========================================================

1. NSOperation

   此类是抽象类不能直接使用。

   只能使用系统定义好的子类或者自定义继承NSOperation。

   定义好的子类:NSInvocationOperation 和 NSBlockOperation

   一个 NSOperation对象 对应一个任务/线程,需要将其放入 NSOperationQueue 任务队列/线程池,才会启动并执行任务/线程。 

 2. NSInvocationOperation

   任务的操作执行在方法中进行

   > [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(..) object:nil]   

 

3. NSBlockOperation

   任务的操作执行在block中进行

   > [NSBlockOperation blockOperationWithBlock:^{

        …

    }]

 

4. NSOperationQueue 将任务添加到任务队列中使其启动执行

   > NSOperationQueue *que = [[NSOperationQueue alloc] init]  // 自定义队列

   > que.name // 队列名称

   > que.maxConcurrentOperationCount  // 最大任务并发数,设置为1时为串行执行任务。默认是-1,表示没有限制,会同时执行队列中的任务。

   > [que addOperation:oper1]  // 将任务添加到队列中以启动执行

 

   除自定义队列外:

   主队列(该队列中的任务在主线程执行):[NSOperationQueue mainQueue]

   当前队列:[NSOperationQueue currentQueue]   

5. 任务间的依赖

   [oper1 addDependency:oper2] // 任务1依赖于任务2,任务1的执行必须等任务2执行完毕后才能开始

   注意此操作必须是在将任务添加到队列前执行!!!

 

6. SDWebImage 图片下载原理运用了NSOperation,NSOperationQueue

 

 

三、GCD============================================================

 

1. GCD:任务,队列

   队列分串行,并行队列。

   串行队列中的任务执行:GCD会FIFO(先进先出)的取出一个任务,执行一个后,再获取下一个,依次类推。

   并行队列中的任务执行:GCD也是按FIFO的方式取出任务,与串行的不同是:取出任务后会放倒别的线程上,然后再取出一个放到另外的线程....。 因为取任务的过程很快,看起来所有任务都是一起执行的。注意:GCD会根据系统资源控制并行的任务数量,任务太多时,不会让所有任务同时执行。

 

2. 从程序上队列分类:

   主队列:(串行队列)dispatch_queue_t qm = dispatch_get_main_queue();

   自定义队列:(可串行,并行)dispatch_queue_t qself = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT); // 通过第二个参数指定队列是串行DISPATCH_QUEUE_SERIAL还是并行DISPATCH_QUEUE_CONCURRENT

   全局并行队列:dispatch_queue_t qg = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

 

3. 队列中添加要执行的任务(同步[阻塞当前线程],异步任务[不阻塞当前线程])

    dispatch_async(qm, ^{

        // 在指定的队列中要执行的任务...

    });

4. 队列组

    多个队列可以放到一个组中。

   // 创建队列组 

   dispatch_group_t group = dispatch_group_create();

 

    dispatch_group_async(group, queue, ^{

        // 在指定的队列组中,添加队列queue, 并在queue中添加任务...

    });

    

    dispatch_group_notify(group, queue, ^{

        // 指定的组里的所有任务完成后,发送通知给指定的队列,并执行一个任务…,通常用于在主队列中更新ui

    });

 

iOS多线程编程

标签:

原文地址:http://www.cnblogs.com/GJ-ios/p/5738637.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!