iOS多线程-GCD(Swift)

作者: 天外丶飞仙 | 来源:发表于2017-08-26 16:03 被阅读237次

    GCD准确的来讲应该叫做并发编程技术,因为swift3.0后GCD使用方式有很大的变化这里用Swift来重新整理一下GCD。

    开发中常见代码

    • 同步执行方法,这句话不执行完,就不会执行下一个任务。同步执行不会开启线程。

      DispatchQueue.global().sync {
            print(Thread.current)
      }
      
    • 异步执行任务,任务没有执行完毕,可以不用等待,异步执行下一个任务 ,具备开启线程的能力! 异步通常又是多线程的代名词!

      DispatchQueue.global().async {
             print(Thread.current)
      }
      
    • 开发中最常见的情形,在子线程执行完任务后回到主线程更新UI。

      DispatchQueue.global().async {
             print(Thread.current)
             DispatchQueue.main.async {
                print(Thread.current)
            }
      }
      

    GCD核心概念

    将任务添加到队列,指定任务执行的方法。

    • 任务
      • OC里面用block 封装,swift是闭包。
      • 就是一个提前准备好的代码块,在需要的时候执行。
    • 队列(负责调度任务)
      • 串行队列: 一个接一个的调度任务
      • 并发队列: 可以同时调度多个任务
    • 任务执行函数(任务都需要在线程中执行!!)
      • 同步执行: 不会到线程池里面去获取子线程!
      • 异步执行: 只要有任务,会去线程池取子线程(主队列除外)
    • Demo
      • 串行队列,同步任务
        //创建串行队列
        let serialQueue = DispatchQueue(label: "SCGCD", attributes: .init(rawValue: 0))
        //同步执行
        for i in 0..<10 {
           serialQueue.sync {
              print(i)
              print(Thread.current)
           }
        }
        
        执行结果是不会开启子线程,顺序执行。
      • 串行队列,异步任务。
        //创建串行队列
        let serialQueue = DispatchQueue(label: "SCGCD", attributes: .init(rawValue: 0))
        //异步步执行
         for i in 0..<10 {
             serialQueue.async {
                 print(i)
                 print(Thread.current)
             }
        }
        
        执行结果是会开启子线程,顺序执行。
      • 并发队列,异步执行。
         //创建并发队列
        let conQueue = DispatchQueue(label: "Mazy", attributes: .concurrent)
        //异步执行
         for i in 0..<10 {
            conQueue.async {
               print(i)
               print(Thread.current)
            }
        }
        
        执行结果是会开启子线程,不是顺序执行。
      • 并发队列,同步执行。
        //创建并发队列
        let conQueue = DispatchQueue(label: "KaitoGCD", attributes: .concurrent)
        //同步执行
        for i in 0..<10 {
           conQueue.sync {
               print(i)
               print(Thread.current)
           }
        }
        
        执行结果是不会会开启子线程,顺序执行。
    • 总结
      • 开不开线程,取决于执行任务的函数,同步不开,异步才能开
      • 开几条线程,取决于队列,串行开一条,并发可以开多条(异步)

    同步任务

    利用同步任务,能够做到任务依赖关系,前一个任务是同步任务,这个任务不执行完,队列就不会调度后面的任务。(应用场景是要等待一个任务执行完再去执行其他的任务)

    • 例子:
      //创建并发队列
      let conQueue = DispatchQueue(label: "KaitoGCD", attributes: .concurrent)
      conQueue.sync {
          print("用户登录\(Thread.current)")
      }
      conQueue.async {
           print("支付\(Thread.current)")
      }
      conQueue.async {
          print("下载\(Thread.current)")
      }
      
      这个代码就会等每次登录操作完成后才是支付和下载。

    全局队列

    let globalQueue = DispatchQueue.global()
    
    • 全局队列其实跟并发队列差不多,都是并发,能够调度多个线程。
    • 全局队列与并发队列区别
      • 1 名称,并发队列取名字,适合于企业开发跟踪错误
      • 2 并发队列在MRC情况下需要使用的dispatch_release(q);//ARC 情况下不需要release !

    主队列

    let globalQueue = DispatchQueue.main
    
    • 主队列其实和串行队列差不多,都是一个一个的执行任务。
    • 主队列和串行队列的区别
      • 串行队列最多只能开启一条线程,可以是子线程。
      • 主队列主要是负责在主线程上执行任务。
    • 主队列特性:以FIFO调度任务,如果主线程上有任务在执行,主队列就不会调度任务。这种特性可能会造成一种死锁的情况(面试常问):
      • 同步任务死锁:当前是在主线程,让主队列执行同步任务!
        override func viewDidLoad() {
            super.viewDidLoad()
            print(1)
            DispatchQueue.main.sync {
                print(Thread.current)
            }
        }
        
        以上代码便是死锁的情况,程序会崩溃,因为viewDidLoad()里面执行的任务和DispatchQueue.main.sync执行的任务互相等待造成死锁。

    延迟执行

    //延迟1秒在子线程中异步执行
    DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 1) {
            print(Thread.current)
    }
    

    一次执行

    Swift3以后原有的Dispatch once已经被废弃了。这里就用OC来写代码例子,在OC用dispatch_once来写单例还是应用的很多的。(ps:Swift写单例真的比OC方便很多)

    static dispatch_once_t onceToken;
     NSLog(@"%ld",onceToken);
    //苹果推荐使用 gcd 一次执行,效率高
    dispatch_once(&onceToken, ^{
        //只会执行一次!!
          NSLog(@"执行了%@",[NSThread currentThread]);
     });
    

    调度组

    用一个调度组,可以监听全局队列的任务,主队列去执行最后的任务

    //调度组
    let group = DispatchGroup()
    //添加任务,让队列调度,任务执行情况,最后通知群组
    DispatchQueue.global().async(group: group, qos: .default, flags: [], execute: { 
                
           print("下载1")
    })
    DispatchQueue.global().async(group: group, qos: .default, flags: [], execute: {
                
         print("下载2")
    })
    DispatchQueue.global().async(group: group, qos: .default, flags: [], execute: {
                
          print("下载3")
     })
    //所有任务执行完毕后,通知
     group.notify(queue: DispatchQueue.main) { 
                
          print("回到主队列更新UI")
     }
    

    相关文章

      网友评论

        本文标题:iOS多线程-GCD(Swift)

        本文链接:https://www.haomeiwen.com/subject/qflydxtx.html