• 同步与异步、串行与并发(转)


    说到多线程,我们必须明白两个概念:线程与队列。我把线程理解为车间的流水线,而队列则决定了每条流水线的工作方式。我们可以往队列中加入任务,并决定该队列在什么线程执行。

    主队列异步执行

     DispatchQueue.main.async {
            print(Thread.current)
            DispatchQueue.main.async {
                print(Thread.current)
                sleep(2)
                print(1)
            }
            print(2)
            DispatchQueue.main.async {
                print(Thread.current)
                print(3)
            }
            sleep(1)
        }
    • 打印结果:

    主队列异步执行.png
    • 分析:上述代码看似异步执行开了子线程,实则不然,DispatchQueue.main.async实际上队列中的任务还是在主线程执行,也就是同步执行。而它与DispatchQueue.main.sync的区别就是它不会造成死锁。
      由于主队列是串行队列,根据先进先出的原则,上述代码的执行顺序是:将sleep(2)print(1)加入队列->print(2)->将print(3)加入队列->sleep(1)->sleep(2)->print(1)->print(3)

    串行队列异步执行

     let serialQueue = DispatchQueue(label: "serial_queue")
        serialQueue.async {
            print(Thread.current)
            serialQueue.async {
                sleep(2)
                print(Thread.current)
                print(1)
            }
            print(2)
            serialQueue.async {
                print(3)
                print(Thread.current)
            }
            sleep(1)
        }
    • 打印结果:


      串行队列异步执行.png
    • 分析:为什么要自定义串行队列与主队列分开来?我们知道主队列就是一个串行队列,而它与普通串行队列在异步执行时有什么区别呢?我们可以尝试打印各个线程中的Thread.current,从结果可以看出,自定义串行队列在异步执行时是创建了支线程的,且因为串行的原因只会创建一个支线程。
      同是串行队列,它的执行顺序同上。

    并发队列异步执行

    let concurrentQueue = DispatchQueue(label: "concurrent_quque", attributes: .concurrent)
        concurrentQueue.async {
            print(Thread.current)
            concurrentQueue.async {
                print(Thread.current)
                sleep(2)
                print(1)
                print(4)
                print(5)
                print(6)
                print(7)
            }
            print(2)
            concurrentQueue.async {
                print(Thread.current)
                print(3)
            }
            sleep(1)
        }
    • 打印结果:

    并发队列异步执行.png
    • 分析:从结果可以看出,并发队列异步执行会开多个线程,其数量等于concurrentQueue.async的调用次数。
      并发队列的特点是它在异步执行时,队列中的任务可以无限接近同时执行。那么问题来了:经过试验,无论我打印多少次,这两段代码都没有体现出并发执行的特性,因为它打结果并没有发生改变。

      image.png

      再观察一下代码,可以发现:第一段异步执行代码中sleep(2)让线程睡了2s,我们把它注释。

      image.png

      多打印几次:

      image.png


      image.png

      因为print(Thread.current)也算一个任务,我们注释掉。

      image.png


      image.png

    结论:

    • 对于主队列,同步、异步执行都不会开线程;
    • 对于主队列以外的队列,同步执行不会开线程,异步执行会开线程;
    • 一般来说,开线程的数量取决于.async的调用次数;
    • 无论是串行还是并发,队列中的任务在一个async{ }中都是顺序执行的;
    • 任务并发是指并发队列在异步执行时多个async{ }中的任务无限接近同时执行。
    • 串行队列异步只会创建一个子线程

    链接:http://www.jianshu.com/p/b9e02ab5b3a4

  • 相关阅读:
    第二周作业
    查找整数
    第八周作业
    第七周作业
    第六周作业
    第五周作业
    第四周作业
    第三周作业
    第二周作业
    7-2求最大值及其下标
  • 原文地址:https://www.cnblogs.com/6duxz/p/7444773.html
Copyright © 2020-2023  润新知