跳转至

队列和任务

任务

block的代码块,包括大括号在内。

任务使用block封装,block没有参数也么没有返回值

执行任务的函数

任务的封装,函数式 先存,CPU调度用的时候就取。异步函数还有底层优先级的封装

队列

队列是一种数据结构,FIFO。

串行队列

dq_width==1

顺序执行。执行完前一个任务之后,再执行后一个任务。

并发量等于1,一次只能执行一个,先调度进来的任务优先执行。所以绝大部分串行队列顺序执行。

并发队列

调度多个任务,并不是执行多个。调度函数会耗时。执行前一个任务后,就可以执行下一个任务。可以有多个任务。

虽然也是FIFO先进来的任务先处理,但任务执行完的时间不确定,和任务的复杂度有关系。

主队列

主队列中的一定是主线程。只是同步会阻塞,异步不会阻塞。

主队列是串行队列。主队列绑定UI线程。主队列在main函数之前自动创建。

同步任务,主列队

  • 在主线程中调用会出现死锁,互相等待
  • 死锁原因:在主线程中添加这个列队的时候,添加列队的这个操作本身就是一个任务,我们把它当作任务A,这个任务也被添加到了主线程的列队中。而同步任务,会等待当前列队中前面的任务执行完毕后接着执行,我们把添加到主线程中的列队中的任务称为任务B,这就产生了一个矛盾,任务B要执行需要等任务A执行完毕后才会执行,而任务A执行完毕需要任务B执行结束(因为任务B在任务A中),这就产生了任务互相等待的情况

异步任务,主列队

  • 没有开启新线程,所有任务都是在主线程中执行的(虽然异步任务有开启新线程的能力,但因为是在主列队,所以无法开启新线程,所有任务都在主线程中执行)
  • 由于只有一个线程可以使用,所以所有任务都是按顺序一个个执行的,一个完毕,执行下一个

函数(同步函数,异步函数)

能够开辟线程

任务的回调是否具备异步性 - 同步性:同步函数会立马执行,异步函数会根据业务需求系统调度情况异步回调。

同步

会阻塞当前线程。

不会开启新线程,所有的任务都是在当前线程。

任务只能一个一个顺序执行。

同步函数阻塞的是同步函数下面的所有代码,包括},和同步函数前面的代码没有任何关系。

必须等待当前语句执行完毕,才会执行下一条语句。

异步

不会阻塞当前线程。

具备开辟新线程的能力,可能会开启新的线程。

异步任务串行队列会开辟一条新的线程,当前串行队列中所有任务按照添加的顺序一个一个执行

异步并发会开辟多条线程,开辟多少条线程由系统决定的。

不用等待当前语句执行完毕,就可以执行下一条语句。

总结

同步会阻塞当前队列中的任务,异步不会阻塞当前队列中的任务。

同步和异步针对的是线程,影响是否开启新的线程能力。

串行和并发针对的是队列,影响任务的执行方式。

队列只负责调度,没有执行任务能力。

任务依赖线程执行。线程依赖线程池。

队列是排队的情况,

将任务添加到队列,并且指定执行任务的函数

同一个队列中的,不一定开启新线程

异步函数,有开启新线程的能力,不一定开启新线程

异步函数在同一个队列(包括并发队列),不一定开启新线程

dispatch_queue_t queue = dispatch_queue_create("haha", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
  NSLog(@"111 - %@",[NSThread currentThread]);
  dispatch_async(queue, ^{
    NSLog(@"222 - %@",[NSThread currentThread]);
  });
});

打印结果:

111 - {number = 37, name = (null)}

222 - {number = 37, name = (null)}