Swift 串行 并行 同步 异步

大前提: 我们这里说的串行同步 串行异步 并行同步 并行异步 都是针对一个队列的多个任务来说明的,只有先认清这个前提,才能很好的理解这几个概念,而不至于在串行、并行、同步、异步之间晕头转向.之后详解多个队列也就很容易了.


一个队列下多个任务的串行同步
// 串行同步
    func syncSample(){
        let queue = DispatchQueue(label: "com.zhengwenxiang")

        queue.sync {

            for i in 0..<10{
                print(" ", i)
            }

            print("current thread is \(Thread.current)")
        }

        queue.sync {

            for i in 20..<30{
                print(" ", i)
            }

            print("current thread02 is \(Thread.current)")
        }

        for i in 100..<110{
            print(" ", i)
        }

        print("Main thread is \(Thread.current)")
    }

image

从输出结果不难看出,队列 queue和主队列在同一个线程上按照出现顺序依次执行(主线程),很显然 queue队列的两个任务堵塞了主线程

我们不妨想象一个场景: 一个 iPhone 生产工厂,只有一条正在运营的生产线,生产线上有着一步一步待组装的 iPhone 元件(工厂就是当前程序,这条生产线就是主线程,元件就是任务,也就是block).
当我们创建一个串行同步队列,里面放入两个任务,例如上面代码queue.sync{},所谓串行就是按顺序执行,所谓同步就是在当前线程中执行.所以,当我们创建一个串行同步队列时,就相当于在上面正在运营的供产线上插入一个包含多个元件的包,本来正在运行的生产线走到这里后,按顺序处理完这个包里的元件再继续向下执行,直至结束.
这里的要点是: 没有创建新的生产线,仅仅是在已有的生产线的塞入几个任务

需要谨记的是: 同步:在当前线程中执行 。异步:在另一条线程中执行

一个队列下多个任务的串行异步
  // 串行异步
    func asyncSample(){
        let queue = DispatchQueue(label: "com.zhengwenxiang")

        queue.async {

            for i in 0..<10{
                print(" ", i)
            }

            print("current thread is \(Thread.current)")
        }

        queue.async {

            for i in 20..<30{
                print(" ", i)
            }

            print("current thread02 is \(Thread.current)")
        }

        for i in 100..<110{
            print(" ", i)
        }
        print("Main thread is \(Thread.current)")
    }

image

看结果:很好的印证了上面的话.异步会创建新线程.串行异步只有创建一条新线程.
同样是上面的场景,现在在生产线上放上了一个包含两个元件的元件包.但是当前生产线无法打开这个包,于是就新建立老板就新建了一条生成先专门处理这类包的生产线,遇到这种包就把它扔到这条生产线上,原来生产线继续执行不去管这个包继续往下执行,这个包到新生产线上呗打开然后按顺序组装,至于这个包里的两个元件什么时候组装完成,已经与原来生产线的的元件哪个先组装完成我们就没法知道..唯一可以确定的是新生成线上的两个元件,一定是元件1组装完成之后再组装元件2.

一个队列下多个任务的并行同步
 // 并行同步
    func conQueueSyncSample(){
        /*
         这个 attributes 参数也可以接受另一个名为 initiallyInactive 的值。如果使用这个值,任务不会被自动执行,而是需要开发者手动去触发。
         */
        let anotherQueue = DispatchQueue(label: "com.zhengwenxiang.con", qos: .utility, attributes: .concurrent)

        //initiallyInactive属性的串行队列
        //  let anotherQueue = DispatchQueue(label: "com.zhengwenxiang.con", qos: .utility, attributes: .initiallyInactive)

        // initiallyInactive属性的并行队列
        //  let anotherQueue = DispatchQueue(label: "com.zhengwenxiang.con", qos: .utility, attributes: [.concurrent, .initiallyInactive])
        //  inactiveQueue = anotherQueue

        anotherQueue.sync {
            for i in 0..<10{
                print(" ", i)
            }

            print("current thread is \(Thread.current)")
        }

        anotherQueue.sync {
            for i in 100..<110{
                print(" ", i)
            }

            print("current thread02 is \(Thread.current)")
        }

image

显然,同步不创建新线程,结果与串行同步一样...我没想通并行同步的意义,可能只是因为并行异步才应运而生的吧

一个队列下多个任务的并行异步
  // 并行异步
    func conQueueAsyncSample(){
        //let anotherQueue = DispatchQueue(label: "com.zhengwenxiang.con", qos: .utility)
        /*
         这个 attributes 参数也可以接受另一个名为 initiallyInactive 的值。如果使用这个值,任务不会被自动执行,而是需要开发者手动去触发。
         */
        let anotherQueue = DispatchQueue(label: "com.zhengwenxiang.con", qos: .utility, attributes: .concurrent)    
        anotherQueue.async {
            for i in 0..<10{
                print(" ", i)
            }

            print("current thread is \(Thread.current)")
        }

        anotherQueue.async {
            for i in 100..<110{
                print(" ", i)
            }

            print("current thread02 is \(Thread.current)")
        }

        //        anotherQueue.async {
        //            for i in 1000..<1010 {
        //                print(" ", i)
        //            }
        //        }

        for i in 2000..<2010 {
            print(" ", i)
        }

        print("Main thread is \(Thread.current)")
    }

image

异步创建新线程,从截图我可以看到,一个有三条线程,一条主线程和两条新线程.
可以想象的是,正如串行一不一样,遇到一个包含 n 个元件的包,当前生产线打不开,老大有钱了,就豪掷千金又给工程装了几条生产线,但是毕竟资金有限, b 不宜装太大,所以不能再新建 n 条生产线,根据实际情况装了几条生产线,装个小 b. 然后把包里的 n 个元件扔到新建的生产线上进行装装同样我们我们也没法主动包里的元件与原来生产线上的元件谁先组装完成.**当然,具体完成顺序可以可控,我们通过给队列设置优先级来控制,比如上面代码,我们设置了anotherQueue队列的优先级是utility(具体优先级设置可以自己查询),所有这里我们的主线程总是在两个新线程前完成组装 **


PS: 具体延伸多个队列的详情,可以通过运行 demo了解,相信上面理解了就能理解.
GCDDemo地址

摘自婉卿容若 本文仅做学习使用 如有侵权 麻烦联系 立即删除

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342