扬庆の博客

任务队列

字数统计: 1.4k阅读时长: 5 min
2022/03/22 Share

任务 队列

一、任务

就是执行的操作的意思,也就是在子线程中执行的那段代码(block块内容)。在GCD中是放在block中的。执行任务有两种方式: 同步执行(sync)和异步执行(async)

同步(Sync)

同步添加任务到指定的队列中,在添加的任务执行结束前,会一直等待,直到队列里面的任务完成之后再继续执行,即会阻塞线程。只能在当前线程中执行任务(当前线程,不一定是主线程),不具备开启新线程的能力。

异步(async)

线程会立即返回,无需等待就会执行下面的任务,不阻塞当前线程。可以在新的线程中执行任务,具备开启新线程的能力(并不一定开启新线程)。如果不是添加到主队列上,异步会在子线程中执行任务


二、队列

队列(Dispatch_queue): 这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊的线性表,采用FIFO(先进先出)的原则,即新任务总是被插入到队列的末尾,而读取任务的时候总是从队列的头部开始读取。每读取一个任务,则从队列中释放一个任务

在GCD中有两种队列: 串行队列(serial dispatch queue),和并发队列 (concurrent dispatch queue)。两则都符合FIFO(先进先出)的原则。两则主要区别是: 执行顺序不同,以及开启线程数不同。

  • 串行队列(serial dispatch queueue):

​ 同一时间内,队列中只能执行一个任务,只有低昂钱的任务执行完成之后,才能执行下一个任务。(只能开启一个 线程,一个任务执行完毕后,再执行下一个任务)。主队列是线程上的一个串行队列,是系统自动为我们创建的。

  • 并发队列(concurrent dispatch queueue):

​ 同时允许多个任务并发执行。(可以开启多个线程,并且同时执行任务)。并发队列的并发功能只有在异步 (dispatch_async)函数下才有效

四、iOS中的多线程

三种:NSThread NSOperationQueue GCD

NSThread 轻量级别的多线程技术

是我们自己手动开辟的子线程,如果使用的是初始化的方式就需要我们自己启动,如果使用的是构造器方式它就会自动启动。

1
2
3
ex:
[NSThread alloc]initWithTarget:]; // 需要手动启动 [thread star];
[NSThread deachNewThreadSelector:]; //会自动启动

只要是我们手动开辟的线程,都需要我们自己管理该线程,不只是启动,还有该线程使用完毕后的资源回收。

performSelector… 只要是NSObject的子类或者对象都可以通过调用方法进入子线程和主线程,其实这些方法所开辟的子线程也是NSThread的另一种体现方式。

在编译阶段并不会去检查方法是否有效存在, 如果不存在只会给出警告⚠️。

图片来自网络

注意:

如果是带afterDelay的延时函数,会在内部创建一个NSTimer, 然后添加到当前线程的Runloop中。也就是当前线程没有开启runloop,该方法会失效。在子线程中,需要启动runloop(注意调用顺序)。

code

result

performSelector只是一个单纯消息发送,和时间没有一点关系。所以不需要添加到子线程的runloop中也能执行。

GCD 对比 NSOperationQueue

先明确 GCD和 NSOperationQueue 的关系

GCD是面向底层的C语言的API,NSOperationQueue 用GCD构建封装的,是GCD的高级抽象。

  1. GCD 执行效率更高,而且由于队列中执行的是由 block 构成的任务,这是一个轻量级的数据结构,写起来更方便
  2. GCD 只支持 FIFO 的队列,而 NSOperationQueue 可以通过设置最大并发数,设置优先级,添加依赖关系等调整顺序
  3. NSOperationQueue甚至可以跨队列设置依赖关系,但是GCD只能通过设置串行队列,或者在并发队列中添加栅栏barrier(dispatch_barrier_async)任务,才能控制执行顺序,较为复杂。
  4. NSOperationQueue 因为面向对象,所以支持KVO,可以监测operation是否正在执行(isExecuted)、是否结束(isFinished)、是否取消(isCanceld)
  • 实际开发中,很多时候只是会用到异步操作,不会有特别复杂的线程关系管理,所以苹果推崇的且优化完善、运行快速的GCD是首选
  • 如果考虑异步操作之间的事物性,顺序性,依赖关系,比如:多线程并发下载,GCD需要自己写更多的代码来实现,而NSOperationQueue已经内建了这些支持
  • 不论是GCD 还是 NSOperationQueue我们接触的都是任务和队列,都没有直接接触到线程,事实上线程管理的确不需要我们操心,系统对于线程的创建、调度管理、释放都做的很好。 而NSThread需要我们自己管理线程声明周期,还要考虑线程同步、枷锁问题,造成一些性能上的开销

队 列

执行任务的等待任务队列。

iOS中,有GCDNSOperationNSThread 等几种多线程技术方案。

而GCD共有三种队列类型:

main queue:通过dispatch_get_main_queue()获得,这是一个与主线程相关的串行队列。

global queue:全局队列是并发队列,由整个进程共享。 存在着高、中、低三种优先级的全局队列。调用dispatch_get_global_queue并传入优先级来访问队列。

自定义队列:通过函数dispatch_queue_create创建的任务队列。

(任务:执行的操作,子线程中block的那段代码)。

CATALOG
  1. 1. 任务 队列
    1. 1.1. 一、任务
    2. 1.2. 同步(Sync)
    3. 1.3. 异步(async)
    4. 1.4. 二、队列
    5. 1.5. 四、iOS中的多线程
      1. 1.5.1. NSThread 轻量级别的多线程技术
        1. 1.5.1.1. 注意:
    6. 1.6. GCD 对比 NSOperationQueue
    7. 1.7. 队 列