iOS新浪微博关于队列的笔试题分析

335 阅读3分钟

这是我参与8月更文挑战的第15天,活动详情查看: 8月更文挑战

我们结合一道新浪微博的笔试题来进行分析,这里我们针对两种不同情况:

  • 并发队列
  • 串行队列

并发

新浪微博笔试题,原题如下:

ABCD四个选项中,选择出哪个选项的打印顺序可能出现?

解析:

  • 1、DISPATCH_QUEUE_CONCURRENT表示队列queue是一个并发队列
  • 2、dispatch_sync(queue, ^{ NSLog(@"3"); })同步函数将会堵塞249行以下的代码,所以3一定比0先打印;
  • 0主队列中,所以0一定比7 8 9先打印;
  • 3、因为NSLog(@"1")NSLog(@"2")都是异步函数,而且都处在并发队列中,所以12的打印顺序是无序的,也就是打印顺序有可能是1先打印,也有可能是2先打印,我们运行看一下打印结果:

结果30之前,12的打印顺序不固定;

  • 4、我们在NSLog(@"3")之前添加代码sleep(2);,看一下打印结果:

异步函数处在并发队列中,将会开启线程,在当前线程中执行任务,任务将会异步执行,没有顺序,其调用顺序与CPU的调度有关,说明1 2 3的打印顺序是不固定的,其顺序由CPU调度决定,而不同设备,不同时刻其CPU调度都可能不一样

最终,由于1 2 3的顺序不固定,但是3一定比0先打印,0一定比7 8 9先打印,7 8 9的顺序也是不固定的,所以最终结果为AC,也就是12307893120798两种结果都有可能出现;

串行

请问,在ABCD四个选项中那个打印顺序是对的?

解析:

  • 1、DISPATCH_QUEUE_SERIAL表示队列queue是一个串行队列;
  • 2、dispatch_sync(queue, ^{ NSLog(@"3"); })同步函数将会堵塞249行以下的代码,所以3一定比0先打印;
  • 3、穿行队列的特性FIFO,也就是先进先出(First In First Out),加入队列的任务将会按照顺序执行,所以2一定在1后边打印;我们可以如下验证一下:

4、我们在NSLog(1)之前休眠了2秒钟,按照我们正常的逻辑,都是异步函数,因为NSLog(1)休眠了2秒钟,按道理应该先打印2,结果打印顺序,依然是1在前,2在后;这是因为,异步函数加入串行队列之后,将会开启一条新的线程来执行队列中的任务,而队列串行队列,所以任务将会一个接着一个的顺序执行

  • 5、后边的同理,打印顺序为 7 8 9;

所以,最终打印结果为1230789,也就是A答案

函数与队列的总结

  • 同步函数串行队列
    • 不会开启线程,在当前线程执行任务
    • 任务串行执行,任务一个接着一个
    • 会产生堵塞
  • 同步函数并发队列
    • 不会开启线程,在当前线程执行任务
    • 任务一个接着一个
  • 异步函数串行队列
    • 开启线程,一条新线程
    • 任务一个接着一个
  • 异步函数兵法队列
    • 开启线程,在当前线程执行任务
    • 任务异步执行,没有顺序,与CPU调度有关

相关文章

如果还是对此有疑问的话,可以看我的另外两篇文章对多线程GCD的介绍:

  • 多线程(文章包含多线程的一些知识)
  • GCD(文章包含函数队列的一些知识及相关面试题)