美文网首页iOS 底层原理iOS实践
iOS 的串行队列和并发队列中的任务是如何执行的

iOS 的串行队列和并发队列中的任务是如何执行的

作者: 栋柠柒 | 来源:发表于2021-11-21 11:53 被阅读0次

我们都知道队列有串行队列和并发队列,主队列就属于串行队列,串行队列里面的任务是按顺序执行,并发队列里的任务是并发执行,至于并发几个线程去执行,这就交给GCD 了。
但是有个问题需要思考一下,我们都知道任务要执行,先要从队列中取出,然后再分配到线程中执行,也就是分三步:1.从队列中取出任务,2.执行任务,3.任务执行完毕。所谓串行队列里面的任务按顺序执行,这个按顺序是指的按顺序取出,还是等前一个任务执行完毕再执行下一个任务呢?写个代码测试一下。

串行队列同步异步执行测试

1.串行队列中同步执行一个任务,异步执行一个任务

let seralQueue = DispatchQueue(label: "dispatchSeralQueue")
//任务一
seralQueue.sync {
            for i in 0...10 {
                debugPrint("queueTest seralQueue1: \(Thread.current), \(i)")
            }
        }
//任务二
        seralQueue.async {
            for i in 0...10 {
                debugPrint("queueTest seralQueue2: \(Thread.current), \(i)")
            }
        }
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 0"
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 1"
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 2"
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 3"
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 4"
"queueTest seralQueue1: <_NSMainThread: 0x600002360540>{number = 1, name = main}, 5"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 0"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 1"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 2"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 3"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 4"
"queueTest seralQueue2: <NSThread: 0x60000235eec0>{number = 4, name = (null)}, 5"

可以看到,第一个任务是在主线程执行,第二个任务在子线程执行,这符合代码逻辑,从输出顺序上来看,在串行队列中,虽然任务二用了异步执行的方式,也开了新的线程,但是顺序却是任务一执行完毕之后,任务二才会执行。

2.串行队列中异步执行两个任务

let seralQueue = DispatchQueue(label: "dispatchSeralQueue")
// 任务一
seralQueue.async {
            for i in 0...5 {
                debugPrint("queueTest seralQueue1: \(Thread.current), \(i)")
            }
        }
//任务 二
        seralQueue.async {
            for i in 0...5 {
                debugPrint("queueTest seralQueue2: \(Thread.current), \(i)")
            }
        }
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 0"
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 1"
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 2"
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 3"
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 4"
"queueTest seralQueue1: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 5"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 0"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 1"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 2"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 3"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 4"
"queueTest seralQueue2: <NSThread: 0x600001cbd700>{number = 6, name = (null)}, 5"

可以看到,两个任务都在子线程执行,而且是按顺序的,第一个任务执行完毕,才会轮到第二个任务执行。

3.串行队列同步执行两个任务

let seralQueue = DispatchQueue(label: "dispatchSeralQueue")
seralQueue.sync {
            for i in 0...5 {
                debugPrint("queueTest seralQueue1: \(Thread.current), \(i)")
            }
        }
        seralQueue.sync {
            for i in 0...5 {
                debugPrint("queueTest seralQueue2: \(Thread.current), \(i)")
            }
        }
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 0"
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 1"
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 2"
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 3"
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 4"
"queueTest seralQueue1: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 5"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 0"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 1"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 2"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 3"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 4"
"queueTest seralQueue2: <_NSMainThread: 0x600002fb0080>{number = 1, name = main}, 5"

同步执行顺序队列任务,没有开启新线程,任务按顺序执行。

并发队列同步异步执行测试

并发队列异步执行两个任务

let conCurrentQueue = DispatchQueue(label: "dispatchConcurrentQueue", attributes: .concurrent)
conCurrentQueue.async {
            for i in 0...5 {
                debugPrint("queueTest conCurrentQueue1: \(Thread.current), \(i)")
            }
        }
        conCurrentQueue.async {
            for i in 0...5 {
                debugPrint("queueTest conCurrentQueue2: \(Thread.current), \(i)")
            }
        }
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 0"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 0"
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 1"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 1"
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 2"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 2"
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 3"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 3"
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 4"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 4"
"queueTest conCurrentQueue2: <NSThread: 0x60000018e780>{number = 5, name = (null)}, 5"
"queueTest conCurrentQueue1: <NSThread: 0x600000189e80>{number = 6, name = (null)}, 5"

可以看到两个任务之间是交叉执行的,并没有顺序关系,而且也开辟了新的线程。

并发队列同步执行两个任务

conCurrentQueue.sync {
            for i in 0...5 {
                debugPrint("queueTest conCurrentQueue1: \(Thread.current), \(i)")
            }
        }
        conCurrentQueue.sync {
            for i in 0...5 {
                debugPrint("queueTest conCurrentQueue2: \(Thread.current), \(i)")
            }
        }
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 0"
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 1"
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 2"
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 3"
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 4"
"queueTest conCurrentQueue1: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 5"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 0"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 1"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 2"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 3"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 4"
"queueTest conCurrentQueue2: <_NSMainThread: 0x60000142c040>{number = 1, name = main}, 5"

可以看到并发队列同步执行,并没有开启新的线程,任务也是按顺序执行完毕的

并发队列中,同步执行一个任务,异步执行一个任务

let conCurrentQueue = DispatchQueue(label: "dispatchConcurrentQueue", attributes: .concurrent)
conCurrentQueue.sync {
            for i in 0...5 {
                debugPrint("queueTest conCurrentQueue1: \(Thread.current), \(i)")
            }
        }
        conCurrentQueue.async {
            for i in 0...5 {
                debugPrint("queueTest conCurrentQueue2: \(Thread.current), \(i)")
            }
        }
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 0"
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 1"
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 2"
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 3"
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 4"
"queueTest conCurrentQueue1: <_NSMainThread: 0x600000d6c000>{number = 1, name = main}, 5"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 0"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 1"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 2"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 3"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 4"
"queueTest conCurrentQueue2: <NSThread: 0x600000d24d40>{number = 7, name = (null)}, 5"

异步执行的任务开启了新的线程,但是两个任务之间还是顺序的关系,一个任务执行完毕,才会开始执行下一个任务。

结论

串行队列+同步执行=不开新线程,任务依次执行
串行队列+异步执行=开启新线程,任务依次执行
并发队列+同步执行=不开新线程,任务依次执行
并发队列+异步执行=开启新线程,任务并发执行

相关文章

  • iOS 的串行队列和并发队列中的任务是如何执行的

    我们都知道队列有串行队列和并发队列,主队列就属于串行队列,串行队列里面的任务是按顺序执行,并发队列里的任务是并发执...

  • 问题[○○○]:谈谈队列和多线程的使用原理

    在iOS中队列分为以下几种:串行队列:队列中的任务只会顺序执行; 并行队列: 队列中的任务通常会并发执行; 全局队...

  • 队列dispatch_queue的使用

    队列分为:串行队列、并发队列和主队列,主队列也叫特殊串行队列,是GCD自带的。 任务的执行分为:同步执行和异步执行...

  • iOS GCD笔记

    串行队列 并发队列 主队列 全局并发队列 同步执行 异步执行 同步+并发队列 = 没有开启新线程,串行执行任务 s...

  • 问题:谈谈队列和多线程的使用原理

    队列分为以下几种: 串行队列:队列中的任务只会顺序执行; 并行队列: 队列中的任务通常会并发执行; 全局队列:是系...

  • iOS开发-队列和同步异步执行的结果分析

    多线程中的队列有:串行队列,并发队列,全局队列(并发),主队列(串行)。 执行的方法有:同步执行和异步执行。 提到...

  • 队列和线程

    [iOS多线程中,队列和执行的排列组合结果分析] 多线程中的队列有:串行队列,并发队列,全局队列,主队列。 执行的...

  • 多线程

    iOS中的几种多线程GCD1、GCD分为任务和队列,任务(同步,异步)队列(串行,并发),同步串行,同步主队列的情...

  • GCD简单使用

    队列类型 并发队列(Concurrent Dispatch Queue)任务并发(同步)执行 串行队列(Seria...

  • iOS线程、队列与死锁

    iOS中关于线程和队列,有一些概念:队列、串行队列、并发队列、主线程、主队列、任务、同步、异步。这些概念的意义和联...

网友评论

    本文标题:iOS 的串行队列和并发队列中的任务是如何执行的

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