zoukankan      html  css  js  c++  java
  • 用例子看Swift4的GCD

      关于GCD基础知识的文章很多,但很多都停留在iOS早期版本的状态,随着iOS的升级GCD的使用也随之升级了,下面举了很多例子来看一看。

    1、串行队列使用同步运行

    ////1、普通队列同步运行
    let queue = DispatchQueue(label:"com.test")
    queue.sync{
        for _ in 0..<6 {
            print("aaaaaaa(Thread.current)")
        }
    }
    for _ in 0..<6  {
        print("bbbbbbb(Thread.current)")
    }  

     运行结果:

    aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

    aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

    aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

    aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

    aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

    aaaaaaa<NSThread: 0x6040002608c0>{number = 1, name = main}

    bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

    bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

    bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

    bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

    bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

    bbbbbbb<NSThread: 0x6040002608c0>{number = 1, name = main}

     

    结果分析:

    串行队形完全阻断了主线程的运行,都使用main线程,这种写法是完全没有意义的。

    2、串行队列使用异步运行

    //2、普通队列异步运行
    let queue = DispatchQueue(label:"com.test")
    queue.async{
        for _ in 0..<6 {
            print("aaaaaaa(Thread.current)")
        }
    }
    for _ in 0..<6  {
        print("bbbbbbb(Thread.current)")
    }
    

    运行结果:

    bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

    aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

    bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

    aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

    bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

    bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

    bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

    bbbbbbb<NSThread: 0x604000066580>{number = 1, name = main}

    aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x600000071680>{number = 3, name = (null)}

     

    运行结果分析:

    串行队列任务与主线程并行,串行队列使用了新的线程3,感觉上就像自己启了一个线程在做事情,使用DispatchQueue会方便很多。

    3、串行队列多次运行

    //3、普通队列异步运行多次
    let queue = DispatchQueue(label:"com.test",qos:DispatchQoS.unspecified)
    queue.async{
        for _ in 0..<6 {
            print("aaaaaaa(Thread.current)")
        }
    }
    queue.async{
        for _ in 0..<6 {
            print("cccccc(Thread.current)")
        }
    }
    for _ in 0..<6  {
        print("bbbbbbb(Thread.current)")
    }

    运行结果:

    bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

    aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

    bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

    bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

    aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

    bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

    aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

    bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

    bbbbbbb<NSThread: 0x60400007cc40>{number = 1, name = main}

    aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x604000264a80>{number = 3, name = (null)}

    cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

    cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

    cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

    cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

    cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

    cccccc<NSThread: 0x604000264a80>{number = 3, name = (null)}

     

    运行结果分析:

    队形中任务与主线程并行且使用了新的线程3,这里可以看处理,串行队列只有等第一个任务运行完才执行第二个(所以aaaaaa打印完,才有cccccc),这里例子很适合做并发中互斥操作,不使用锁。

    4、并行队列异步运行多次

    //4、并行队列异步运行多次
    let queue = DispatchQueue(label:"com.test",qos:DispatchQoS.unspecified,attributes:.concurrent)
    queue.async{
        for _ in 0..<6 {
            print("aaaaaaa(Thread.current)")
        }
    }
    queue.async{
        for _ in 0..<6 {
            print("cccccc(Thread.current)")
        }
    }
    for _ in 0..<6  {
        print("bbbbbbb(Thread.current)")
    }  

    运行结果:

    bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

    aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

    cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

    bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

    aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

    cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

    bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

    cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

    bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

    aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

    bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

    bbbbbbb<NSThread: 0x604000079c00>{number = 1, name = main}

    cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

    cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

    cccccc<NSThread: 0x600000267380>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

    aaaaaaa<NSThread: 0x6040002657c0>{number = 4, name = (null)}

     

    运行结果分析:

    并行队列的2个任务与主线程同时运行,并行队列中任务分别使用线程3和线程4,这是一个并发的场景,比如我们一边加载不同图片一边不会影响UI的响应;这里也可以看出串行队列与并行队列的不同之处。

    5、多个串行队列异步运行

    let queue = DispatchQueue(label:"com.test",qos:DispatchQoS.unspecified)
    let queue2 = DispatchQueue(label:"com.test",qos:DispatchQoS.userInteractive)
    queue.async{
        for _ in 0..<16 {
            print("aaaaaaa(Thread.current)")
        }
    }
    queue2.async{
        for _ in 0..<16 {
            print("cccccc(Thread.current)")
        }
    }

    运行结果:

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    cccccc<NSThread: 0x60400006ec80>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

    aaaaaaa<NSThread: 0x60400006ecc0>{number = 4, name = (null)}

     

    运行结果分析:

    例子中队列2的优先级比队列1高,所以cccccc在aaaaaa之前打印完,2个不同的串行队列使用不同的线程3和4,并行队列的优先级比较也是一样的结果,这里就不发例子

    6、使用DispatchGroup做任务依赖

    queue先做一个短任务,并行的queue2做一个长任务,等2个任务都做完group通知queue接着做任务,任务C依赖与任务A和任务B同时完成。

    let queue = DispatchQueue(label:"com.test",qos:DispatchQoS.unspecified)
    let queue2 = DispatchQueue(label:"com.test",qos:DispatchQoS.userInteractive)
    let group = DispatchGroup()
    queue.async(group: group, execute: {
        for _ in 0..<3 {
            print("aaaaaaa(Thread.current)")
        }
    })
    queue2.async(group: group, execute: {
        for _ in 0..<6 {
            print("bbbbb(Thread.current)")
        }
    })
    
    //执行完上面的两个耗时操作, 回到queue队列中执行下一步的任务
    group.notify(queue: queue) {
        print("回到queue该队列中执行")
        for _ in 0..<3 {
            print("bbbbb(Thread.current)")
        }
    }

     运行结果:

    bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x604000078580>{number = 4, name = (null)}

    bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x604000078580>{number = 4, name = (null)}

    bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

    aaaaaaa<NSThread: 0x604000078580>{number = 4, name = (null)}

    bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

    bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

    bbbbb<NSThread: 0x604000078540>{number = 3, name = (null)}

    回到queue该队列中执行

    cccccc<NSThread: 0x604000078580>{number = 4, name = (null)}

    cccccc<NSThread: 0x604000078580>{number = 4, name = (null)}

    cccccc<NSThread: 0x604000078580>{number = 4, name = (null)}

     

    运行结果分析:

    2任务分别运行做线程3和4,等他们都做完再到queue中打印cccccc

    7、使用DispatchGroup做任务等待

    queue和queue2是2个并行的队列,queue2中sleep(UInt32(3))可以让queue2超时

     
    let queue = DispatchQueue(label:"com.test",qos:DispatchQoS.unspecified)
    let queue2 = DispatchQueue(label:"com.test",qos:DispatchQoS.userInteractive)
    let group = DispatchGroup()
    queue.async(group: group, execute: {
        for _ in 0..<3 {
            print("aaaaaaa(Thread.current)")
        }
    })
    queue2.async(group: group, execute: {
        for _ in 0..<6 {
            print("bbbbb(Thread.current)")
        }
        //sleep(UInt32(3))
    })
    
    //等待上面任务执行,会阻塞当前线程,超时就执行下面的,上面的继续执行。可以无限等待 .distantFuture
    let result:DispatchTimeoutResult = group.wait(timeout: .now() + 2.0)
    switch result {
    case .success:
        print("不超时, 上面的两个任务都执行完")
    case .timedOut:
        print("超时了, 上面的任务还没执行完执行这了")
    }
    
    print("接下来的操作")
    

      

    打开sleep(UInt32(3)) 的结果:

    aaaaaaa<NSThread: 0x604000273140>{number = 4, name = (null)}
    bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
    aaaaaaa<NSThread: 0x604000273140>{number = 4, name = (null)}
    bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
    bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
    bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
    aaaaaaa<NSThread: 0x604000273140>{number = 4, name = (null)}
    bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
    bbbbb<NSThread: 0x6000004703c0>{number = 3, name = (null)}
    超时了, 上面的任务还没执行完执行这了
    接下来的操作

    注解sleep(UInt32(3))结果:

    bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
    aaaaaaa<NSThread: 0x600000278e00>{number = 4, name = (null)}
    aaaaaaa<NSThread: 0x600000278e00>{number = 4, name = (null)}
    bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
    aaaaaaa<NSThread: 0x600000278e00>{number = 4, name = (null)}
    bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
    bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
    bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
    bbbbb<NSThread: 0x604000273280>{number = 3, name = (null)}
    不超时, 上面的两个任务都执行完
    接下来的操作

    结果分析:

    可以用Group的wait方法来做超时判断。

    ps:例子多了点,都是一个一个字码的,系统对学习Swift的GCD有用。

  • 相关阅读:
    用UltraISO制作U盘启动盘及设BIOS从U盘启动的方法
    Android 超链接 打开网址
    ActionScript常用正则表达式收集
    Android模拟器安装,使用APK文件
    正则表达式的规则
    WORD的批注
    机械迷城 迷宫全图
    mysql新建用户及授权
    验证IP是否合法
    ThinkPad水货靠谱店
  • 原文地址:https://www.cnblogs.com/sakaiPeng/p/9808733.html
Copyright © 2011-2022 走看看