zoukankan      html  css  js  c++  java
  • 同步与异步、串行与并发(转)

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

    主队列异步执行

     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

  • 相关阅读:
    【转】 java中Class对象详解和类名.class, class.forName(), getClass()区别
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    107. Binary Tree Level Order Traversal II
    109. Convert Sorted List to Binary Search Tree
    108. Convert Sorted Array to Binary Search Tree
    110. Balanced Binary Tree
    STL容器迭代器失效问题讨论
    113. Path Sum II
    112. Path Sum
  • 原文地址:https://www.cnblogs.com/6duxz/p/7444773.html
Copyright © 2011-2022 走看看