美文网首页iOS Developer
iOS 多线程小结

iOS 多线程小结

作者: PersonChen_QJ | 来源:发表于2018-05-09 09:22 被阅读239次

关于多线程

  • 概念:
  • 同一个进程中同时开启多个线程,每条线程执行不同的任务。
  • 本质:速度快
  • 同一时间,CPU只能处理一条线程,意味着只有一条线程在执行。
  • CPU以人类难以察觉的速度在不同的线程之间切换,造成多条线程并发执行的假象。
  • 如果线程非常非常多,CPU切换频繁,消耗大量资源,线程执行效率降低。
  • 优点:
  • 多条线程同时(并发)执行,提高程序的执行效率。
  • 提高资源利用率,包括CPU、内存等。
  • 缺点
  • 开启新线程会占用一定内存,线程过多会降低性能。
  • 2.程序设计更加复杂,比如线程之间的通信、多条线程的数据共享。
  • 附:本文目录


    iOS多线程.png

一、基本概念

  • 进程
  • 可以理解成一个运行中的应用程序,是系统进行资源分配和调度的基本单位,是操作系统结构的基础,主要管理资源。
  • 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。
  • 线程
  • 线程是进程的基本执行单元,即进程想要执行任务,必须得有线程。
  • 程序执行流的最小单元,线程是进程中的一个实体。
  • 同步线程
  • 在当前线程内按照创建的先后顺序依次执行,不开启新线程。
  • 异步线程
  • 在当前线程内开启多个新的线程,同时运行,无先后关系。
  • 队列
  • 装载线程任务的队形结构。
  • 并发
  • 线程执行可以同时一起进行执行。
  • 串行
  • 线程执行只能依次逐一先后有序的执行。
  • 线程通讯
  • 在一个进程中,通常有多个线程,线程不是孤立存在的,线程之前需要"沟通交流"。
注意点
  • 一个进程可有多个线程。
  • 一个进程可有多个队列。
  • 队列可分并发队列和串行队列。

二、创建方式

  • NSThread
  • 每个NSThread对象对应一个线程,真正最原始的线程。
  • 优点
  • NSThread 轻量级最低,相对简单。
  • 可直接操作线程对象。
  • 缺点
  • 手动管理所有的线程活动,如生命周期、线程同步、睡眠等。
  • NSOperation
  • 自带线程管理的抽象类。
  • 优点
  • 自带线程周期管理,操作上可更注重自己逻辑。
  • 缺点
  • 面向对象的抽象类,只能实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。
  • GCD

*Grand Central Dispatch是由苹果开发的一个多核编程的解决方案。iOS4.0+才能使用。

  • 优点
  • 最高效,避开并发陷阱。
  • 苹果官方推荐使用。
  • 使用比上面2种更为简单。
  • 性能更好,GCD自动根据系统负载来增减线程数量,这就减少了上下文切换以及增加了计算效率。
  • 开发者只需要告诉 GCD 想要如何执行什么任务,不需要编写任何线程管理代码。
  • 缺点
  • 基于C实现。

三、如何选择

  • 简单而安全的选择NSOperation实现多线程即可。
  • 处理大量并发数据,又追求性能效率的选择GCD。
  • NSThread本人选择基本上是在做些小测试上使用。
  • 个人推荐使用gcd。

四、生命周期

  • 无论使用哪种方式创建的线程,在正常情况下它的生命周期都是一样的。


    状态示意图.png
  • 概念
    新建:实例化线程对象

  • 就绪:向线程对象发送start消息,线程对象被加入可调度线程池等待CPU调度。
  • 运行:CPU 负责调度可调度线程池中线程的执行。线程执行完成之前,状> * 态可能会在就绪和运行之间来回切换。就绪和运行之间的状态变化由CPU负> * 责,程序员不能干预。
  • 阻塞:当满足某个预定条件时,可以使用休眠或锁,阻塞线程执行。sleepForTimeInterval(休眠指定时长),sleepUntilDate(休眠到指定日期),@synchronized(self):(互斥锁)。
  • 死亡:正常死亡,线程执行完毕。非正常死亡,当满足某个条件后,在线程> * 内部中止执行/在主线程中止线程对象
  • 还有线程的exit和cancel
  • [NSThread exit]:一旦强行终止线程,后续的所有代码都不会被执行。
  • [thread cancel]取消:并不会直接取消线程,只是给线程对象添加 isCancelled 标记。

五、使用方法(详细介绍GCD的使用方法)

  • NSThread 创建线程
    //动态创建线程
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction:) object:@"one"];
    thread.threadPriority = 1;
    [thread start];
    
    //静态创建线程
    [NSThread detachNewThreadSelector:@selector(threadAction:) toTarget:self withObject:@"two"];
    
    //隐式创建线程
    [self performSelectorInBackground:@selector(threadAction:) withObject:@"three"];

   //响应方法
    -(void)threadAction:(id)object
    {
        NSLog(@"object = %@",object);
    }
  • 线程通讯
//在指定线程上执行操作
[self performSelector:@selector(threadAction:) onThread:thread withObject:nil waitUntilDone:YES]; 
//在主线程上执行操作
[self performSelectorOnMainThread:@selector(threadAction:) withObject:nil waitUntilDone:YES]; 
//在当前线程执行操作
[self performSelector:@selector(threadAction:) withObject:nil];
  • NSOperation
//NSInvocationOperation创建线程。
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadAction:) object:@"six"];
//[invocationOperation start];//直接会在当前线程主线程执行
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperation:invocationOperation];

GCD

1.任务和队列
  • 1.1 任务
  • 就是执行操作的意思,换句话说就是你在线程中执行的那段代码。在 GCD 中是放在 block 中的。
  • 执行任务有两种方式:同步执行(sync)和异步执行(async)。两者的主要区别是:是否等待队列的任务执行结束,以及是否具备开启新线程的能力。
同步执行(sync):
    * 同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后再继续执行。
    * 只能在当前线程中执行任务,不具备开启新线程的能力。
异步执行(async):
    * 异步添加任务到指定的队列中,它不会做任何等待,可以继续执行任务。
    * 可以在新的线程中执行任务,具备开启新线程的能力。

1.2 队列

  • 这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊的线性表,采用 FIFO(先进先出)的原则,即新任务总是被插入到队列的末尾,而读取任务的时候总是从队列的头部开始读取。每读取一个任务,则从队列中释放一个任务。
  • 在 GCD 中有两种队列:串行队列和并发队列。两者都符合 FIFO(先进先出)的原则。两者的主要区别是:执行顺序不同,以及开启线程数不同。
串行队列(Serial Dispatch Queue):
     * 每次只有一个任务被执行。让任务一个接着一个地执行。(只开启一个线程,一个任务执行完毕后,再执行下一个任务)
     * 对于串行队列,GCD 提供了的一种特殊的串行队列:主队列(Main Dispatch Queue),所有放在主队列中的任务,都会放到主线程中执行。
并发队列(Concurrent Dispatch Queue):
     * 可以让多个任务并发(同时)执行。(可以开启多个线程,并且同时执行任务)
注意:并发队列的并发功能只有在异步(dispatch_async)函数下才有效
     * 对于并发队列,GCD 默认提供了全局并发队列(Global Dispatch Queue)。
2. GCD使用步骤
  • 创建一个队列(串行队列或并发队列)
  • 将任务追加到任务的等待队列中,然后系统就会根据任务类型执行任务(同步执行或异步执行)
3. 队列的创建
  • 可以使用dispatch_queue_create来创建队列,需要传入两个参数,第一个参数表示队列的唯一标识符,用于 DEBUG,可为空,Dispatch Queue 的名称推荐使用应用程序 ID 这种逆序全程域名;第二个参数用来识别是串行队列还是并发队列。DISPATCH_QUEUE_SERIAL 表示串行队列,DISPATCH_QUEUE_CONCURRENT 表示并发队列。
// 串行队列的创建方法
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);
// 并发队列的创建方法
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);
4. 任务的创建
  • GCD 提供了同步执行任务的创建方法dispatch_sync和异步执行任务创建方法dispatch_async。
// 同步执行任务创建方法
dispatch_sync(queue, ^{
    // 这里放同步执行任务代码
});
// 异步执行任务创建方法
dispatch_async(queue, ^{
    // 这里放异步执行任务代码
});
5. 基本使用
组合方式对比.png
  • 同步执行 + 并发队列


    同步执行 + 并发队列.png

    从上图可以看出:

  • 所有任务都是在当前线程(主线程)中执行的,没有开启新的线程(同步执行不具备开启新线程的能力)。
  • 所有任务都在打印的syncConcurrent---begin和syncConcurrent---end之间执行的(同步任务需要等待队列的任务执行结束)。
  • 任务按顺序执行的。按顺序执行的原因:虽然并发队列可以开启多个线程,并且同时执行多个任务。但是因为本身不能创建新线程,只有当前线程这一个线程(同步任务不具备开启新线程的能力),所以也就不存在并发。而且当前线程只有等待当前队列中正在执行的任务执行完毕之后,才能继续接着执行下面的操作(同步任务需要等待队列的任务执行结束)。所以任务只能一个接一个按顺序执行,不能同时被执行。
  • 特点:在当前线程中执行任务,不会开启新线程,执行完一个任务,再执行下一个任务。
  • 异步执行 + 并发队列


    异步执行 + 并发队列.png

从上图可以看出:

  • 除了当前线程(主线程),系统又开启了3个线程,并且任务是交替/同时执行的。(异步执行具备开启新线程的能力。且并发队列可开启多个线程,同时执行多个任务)。
  • 所有任务是在打印的syncConcurrent---begin和syncConcurrent---end之后才执行的。说明当前线程没有等待,而是直接开启了新线程,在新线程中执行任务(异步执行不做等待,可以继续执行任务)。
  • 特点:可以开启多个线程,任务交替(同时)执行。
  • 同步执行 + 串行队列


    同步执行 + 串行队列.png

从上图可以看出:

  • 所有任务都是在当前线程(主线程)中执行的,并没有开启新的线程(同步执行不具备开启新线程的能力)。
  • 所有任务都在打印的syncConcurrent---begin和syncConcurrent---end之间执行(同步任务需要等待队列的任务执行结束)。
  • 任务是按顺序执行的(串行队列每次只有一个任务被执行,任务一个接一个按顺序执行)。
  • 特点:不会开启新线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务。
  • 异步执行 + 串行队列


    异步执行 + 串行队列.png

    从上图可以看出:

  • 开启了一条新线程(异步执行具备开启新线程的能力,串行队列只开启一个线程)。
  • 所有任务是在打印的syncConcurrent---begin和syncConcurrent---end之后才开始执行的(异步执行不会做任何等待,可以继续执行任务)。
  • 任务是按顺序执行的(串行队列每次只有一个任务被执行,任务一个接一个按顺序执行)。
  • 特点:会开启一条新线程,但是因为任务是串行的,执行完一个任务,再执行下一个任务。

结尾

  • 以上纯属个人观点,如有不对欢迎指出。

相关文章

  • iOS-多线程

    iOS开发中常用的几种多线程方案,简单做个小结,方便日后查阅。 NSThead GCD NSOperation &...

  • iOS开发-多线程学习

    iOS开发中常用的几种多线程方案,简单做个小结,方便日后查阅。 Pthreads NSThead GCD NSOp...

  • iOS多线程相关面试题

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • 多线程之--NSOperation

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • iOS多线程之--NSThread

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • iOS多线程小结

    同步异步串行并行 同步串行:不开启线程 同步并行:不开启线程 异步串行:最多开启一个线程 异步并行:开启线程 同步...

  • iOS 多线程小结

    关于多线程 概念: 同一个进程中同时开启多个线程,每条线程执行不同的任务。 本质:速度快 同一时间,CPU只能处理...

  • iOS 多线程小结

    写此文章是为了能够加深自己的记忆,并且对技术点有个记录,方便查阅 这篇文章主要写一些iOS多线程的操作 1.NST...

  • iOS 多线程小结

    在 iOS 中其实目前有 4 套多线程方案,他们分别是:Pthreads、NSThread、GCD、 NSOpe...

  • iOS - 多线程(一):初识

    iOS - 多线程 系列文章 iOS - 多线程(一):初识iOS - 多线程(二):pthread、NSThre...

网友评论

    本文标题:iOS 多线程小结

    本文链接:https://www.haomeiwen.com/subject/vbfwrftx.html