• iOS多线程编程


    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

        });

  • 相关阅读:
    郊原的青草
    基本类型接口(二、EIMI)
    一个简单的委托
    基本类型泛型(二)
    基本类型可空值类型
    基本类型委托(二)
    类型的设计事件
    原码、补码和反码
    基本类型接口(一、您了解接口继承吗?)
    arcgis api for flex 开发入门(一)环境搭建<转>
  • 原文地址:https://www.cnblogs.com/GJ-ios/p/5738637.html
Copyright © 2020-2023  润新知