并发编程 - GCD的任务和队列

2024-08-29 10:36
文章标签 并发 编程 队列 任务 gcd

本文主要是介绍并发编程 - GCD的任务和队列,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引言

在并发编程的世界中,我们可以从开发中最常用的 Grand Central Dispatch (GCD) 开始着手。相比于其他多线程方案,GCD 具备诸多优势:

  • 支持多核并行计算
  • 自动利用多核 CPU 的资源
  • 自动管理线程的生命周期
  • 提供两个可直接使用的队列(主队列和全局队列)
  • 允许我们创建自定义队列

在 GCD 中,最核心的两个概念便是任务队列

任务

任务就是执行操作的意思也就是我们在线程中执行的那一段代码,在GCD中就是放在block里面的代码。

而执行任务有两种方式:

同步执行(sync):

  1. 同步添加任务到指定的队列中,任务会顺序执行,在上一个任务结束之前,当前任务会一直等待,直到队列里面的任务完成后再继续执行。
  2. 只能在当前的线程中执行任务,不具备开启新线程的能力。

异步执行(async):

  1. 异步添加任务到指定的队列中,它不会做任何等待,可以继续执行任务。
  2. 可以在新的现场中执行任务,具备开启新线程的能力。

这两者的主要区别在于:是否等待队列的任务执行结束,以及是否具备开启新线程的能力。

简单来讲,同步同时只能做一件事儿,而异步可以同时做多件事儿。

但是有一个非常需要注意的一点:异步执行(async)虽然具备开启新线程的能力,但是并不一定就会开启新的线程,这还和任务指定的队列类型有关。

队列

队列指的是执行任务的队列,队列是一种特殊的线性表,采用FIFO(先进先出)的原则,新的任务总是被插入到队列的末尾。而任务在执行时总是从队列的最头部开始读取执行。

队列的概念大家应该并不陌生,队列先进先出,栈先进后出,在这里就不过多介绍了。

在GCD中队列也是有两种:

串行队列(Serial Dispatch Queue):

  • 在串行队列中每次只能有一个任务被执行,队列中的所有任务都需要按顺序执行,在串行队列中可能会开启新的线程。

并发队列(Concurrent Dispatch Queue):

  • 在并发队列中任务可以同时执行,可以开启多个线程同时执行任务。

两者的主要区别在于队列中的任务执行顺序不同。

同样值得注意的是并发队列的并发功能只有在执行异步任务时才有效。

关于队列和任务的组合我们先给出两个图片直观的感受一下,然后我们再来详细的讨论一下它们的使用场景。

使用任务和队列

GCD之所以在并发编程中比较受欢迎的原因就是使用起来很容易,只需要两个步骤:

  1. 创建队列
  2. 将任务添加到队列

创建队列

使用DispatchQueue提供的初始化方法直接创建串行队列和并发队列。

        //1.创建一个串行队列let queue = DispatchQueue(label: "com.louis.GCDTestManager")//2.创建一个并发队列let queue1 = DispatchQueue(label: "com.louis.GCDTestManager1", qos: .default, attributes: .concurrent)

另外GCD还提供了两个特殊的队列:主队列(Main Queue)和全局队列(Global Queue)。

        //3.主队列let mainQueue = DispatchQueue.main//4.全局队列let globalQueue = DispatchQueue.global()

主队列属于串行队列,与主线程关联。全局队列属于并发队列,由系统提供。

创建任务

有了队列之后我们就可以在指定的队列中执行任务。

        //1.同步执行任务queue.sync {for i in 0...10 {print("同步执行任务1:\(i)")}}//2.异步执行任务queue.async {for i in 0...10 {print("异步执行任务1:\(i)")}}

在上面的代码中我们都采用了串行队列来进行同步和异步执行任务。

队列和任务组合

不管是队列还是任务的创建都非常容易,但是当我们使用它们时并没有这么简单,我们需要根据场景来判断队列和任务该如何组合,那我们就需要知道每一个组合的结果。

我们先来讨论比较简单的串行队列。

串行队列+同步任务

任务将会在当前线程中执行,不会开启新的线程。任务会按顺序一个一个执行。

代码如下:

    /// 同步任务 + 串行队列func syncSerial() {// 当前线程print("当前线程:\(Thread.current)")// 开始print("syncSerial 开始")//1.创建一个串行队列let queue = DispatchQueue(label: "com.louis.GCDTestManager")//2.同步执行任务1queue.sync {for i in 0...10 {print("同步任务1:\(i)" + "---当前线程:\(Thread.current)")}}//3.同步执行任务2queue.sync {for i in 0...10 {print("同步任务2:\(i)" + "---当前线程:\(Thread.current)")}}print("syncSerial 结束")}

结果如下:

当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

syncSerial 开始

同步任务1:0---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务1:1---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务1:2---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务1:3---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务1:4---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务1:5---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务1:6---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务1:7---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务1:8---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务1:9---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务1:10---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:0---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:1---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:2---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:3---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:4---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:5---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:6---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:7---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:8---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:9---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

同步任务2:10---当前线程:<_NSMainThread: 0x301cac000>{number = 1, name = main}

syncSerial 结束

  1. 可以发现所有的任务当前线程中执行,没有开启新的线程。
  2. 所有任务都在“syncSerial 开始”和“syncSerial 结束”之间。
  3. 所有任务都是按顺序执行的。
串行队列+异步任务

可能会开启新的线程,但由于是串行队列任务仍然会按顺序执行,一个任务执行完再执行另一个任务。

代码如下:

    /// 异步任务 + 串行队列func asyncSerial() {// 当前线程print("当前线程:\(Thread.current)")// 开始print("asyncSerial 开始")//1.创建一个串行队列let queue = DispatchQueue(label: "com.louis.GCDTestManager")//2.异步执行任务1queue.async {for i in 0...10 {print("异步任务1:\(i)" + "---当前线程:\(Thread.current)")}}//3.异步执行任务2queue.async {for i in 0...10 {print("异步任务2:\(i)" + "---当前线程:\(Thread.current)")}}print("asyncSerial 结束")}

结果如下:

当前线程:<_NSMainThread: 0x3000bc040>{number = 1, name = main}

asyncSerial 开始

asyncSerial 结束

异步任务1:0---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务1:1---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务1:2---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务1:3---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务1:4---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务1:5---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务1:6---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务1:7---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务1:8---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务1:9---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务1:10---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:0---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:1---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:2---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:3---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:4---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:5---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:6---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:7---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:8---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:9---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

异步任务2:10---当前线程:<NSThread: 0x3000e8340>{number = 3, name = (null)}

  1. 开启了新的线程。
  2. 所有任务仍然是顺序执行的。
  3. 所有任务都是在asyncSerial 结束之后执行的,说明异步不会阻塞当前线程。
并发队列+同步任务

任务在当前线程中执行,不会开启新的线程,任务按顺序执行。

代码如下:

    /// 同步任务 + 并发队列func syncConcurrent() {// 当前线程print("当前线程:\(Thread.current)")// 开始print("syncConcurrent 开始")//1.创建一个并发队列let queue = DispatchQueue(label: "com.louis.GCDTestManager", attributes: .concurrent)//2.同步执行任务1queue.sync {for i in 0...10 {print("同步任务1:\(i)" + "---当前线程:\(Thread.current)")}}//3.同步执行任务2queue.sync {for i in 0...10 {print("同步任务2:\(i)" + "---当前线程:\(Thread.current)")}}print("syncConcurrent 结束")}

结果如下:

当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

syncConcurrent 开始

同步任务1:0---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务1:1---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务1:2---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务1:3---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务1:4---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务1:5---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务1:6---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务1:7---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务1:8---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务1:9---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务1:10---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:0---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:1---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:2---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:3---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:4---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:5---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:6---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:7---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:8---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:9---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

同步任务2:10---当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

syncConcurrent 结束

  1. 所有任务都在当前线程执行。
  2. 所有任务都在“syncConcurrent 开始”和“syncConcurrent 结束”之间执行。
  3. 任务顺序执行,因为都是同步任务,所以即使在并发队列中它也不具备开启新线程的能力。
并发队列+异步任务

可以开启多个线程,任务同时执行,没有固定顺序。

代码如下:

   /// 异步任务 + 并发队列func asyncConcurrent() {// 当前线程print("当前线程:\(Thread.current)")// 开始print("asyncConcurrent 开始")//1.创建一个并发队列let queue = DispatchQueue(label: "com.louis.GCDTestManager", attributes: .concurrent)//2.异步执行任务1queue.async {for i in 0...10 {print("异步任务1:\(i)" + "---当前线程:\(Thread.current)")}}//3.异步执行任务2queue.async {for i in 0...10 {print("异步任务2:\(i)" + "---当前线程:\(Thread.current)")}}print("asyncConcurrent 结束")}

结果如下:

当前线程:<_NSMainThread: 0x3009f8100>{number = 1, name = main}

asyncConcurrent 开始

asyncConcurrent 结束

异步任务1:0---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务1:1---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务1:2---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务1:3---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务1:4---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务2:0---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

异步任务2:1---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

异步任务2:2---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

异步任务1:5---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务1:6---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务1:7---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务2:3---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

异步任务1:8---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务2:4---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

异步任务1:9---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务2:5---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

异步任务1:10---当前线程:<NSThread: 0x3009ac200>{number = 9, name = (null)}

异步任务2:6---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

异步任务2:7---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

异步任务2:8---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

异步任务2:9---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

异步任务2:10---当前线程:<NSThread: 0x3009a8000>{number = 10, name = (null)}

  1. 开了多个线程。
  2. 任务执行没有固定顺序。
  3. 所有任务都在“asyncConcurrent 结束”之后执行,说明没有阻塞线程。

主队列

分析完了所有任务和队列的组合和结构,我们还需要格外注意一下主队列,主队列属于串行队列,但由于我们的代码默认在主队列上执行所以在进行组合时会有些不一样的效果。

主队列+同步任务

在主队列中同步执行任务会直接卡死崩溃。

代码如下:

    /// 同步任务 + 主队列func syncMain() {// 当前线程print("当前线程:\(Thread.current)")// 开始print("syncMain 开始")//1.获取主队列let queue = DispatchQueue.main//2.同步执行任务1queue.sync {for i in 0...10 {print("同步任务1:\(i)" + "---当前线程:\(Thread.current)")}}//3.同步执行任务2queue.sync {for i in 0...10 {print("同步任务2:\(i)" + "---当前线程:\(Thread.current)")}}print("syncMain 结束")}

结果直接崩溃:

因为当我们把同步任务1添加到主队列时,它会等待当前队列中的任务执行完成再来执行任务1。

但是由于我们把任务1添加到了主队列,主队列又需要等待任务1执行完成才能继续执行。

这样就造成了相互等待,所以就卡死了。

但是如果我们并不是在主线程调用这个方法,那么就不会出现问题。

修改代码如下:

    /// 同步任务 + 主队列func syncMain() {let thread = Thread(target: self, selector: #selector(startSyncMain), object: nil)thread.start()}@objc func startSyncMain() {// 当前线程print("当前线程:\(Thread.current)")// 开始print("syncMain 开始")//1.获取主队列let queue = DispatchQueue.main//2.同步执行任务1queue.sync {for i in 0...10 {print("同步任务1:\(i)" + "---当前线程:\(Thread.current)")}}//3.同步执行任务2queue.sync {for i in 0...10 {print("同步任务2:\(i)" + "---当前线程:\(Thread.current)")}}print("syncMain 结束")}

结果如下:

当前线程:<NSThread: 0x301d200c0>{number = 7, name = (null)}

syncMain 开始

同步任务1:0---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务1:1---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务1:2---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务1:3---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务1:4---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务1:5---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务1:6---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务1:7---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务1:8---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务1:9---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务1:10---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:0---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:1---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:2---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:3---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:4---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:5---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:6---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:7---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:8---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:9---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

同步任务2:10---当前线程:<_NSMainThread: 0x301d6c100>{number = 1, name = main}

syncMain 结束

  1. 所有任务都在主线程中执行。
  2. 所有任务顺序执行。
  3. 所有任务都在“syncMain 开始”和“syncMain 结束”之间执行。

主队列+异步任务

不会开启新的线程,任务顺序执行。

代码如下:

    /// 异步任务 + 主队列func asyncMain() {// 当前线程print("当前线程:\(Thread.current)")// 开始print("asyncMain 开始")//1.获取主队列let queue = DispatchQueue.main//2.异步执行任务1queue.async {for i in 0...10 {print("异步任务1:\(i)" + "---当前线程:\(Thread.current)")}}//3.异步执行任务2queue.async {for i in 0...10 {print("异步任务2:\(i)" + "---当前线程:\(Thread.current)")}}print("asyncMain 结束")}

结果如下:

当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

asyncMain 开始

asyncMain 结束

异步任务1:0---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务1:1---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务1:2---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务1:3---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务1:4---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务1:5---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务1:6---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务1:7---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务1:8---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务1:9---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务1:10---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:0---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:1---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:2---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:3---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:4---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:5---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:6---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:7---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:8---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:9---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

异步任务2:10---当前线程:<_NSMainThread: 0x3028c4100>{number = 1, name = main}

  1. 所有任务都在主线程中执行,没有开启新的线程。
  2. 任务都是在“asyncMain 结束”之后执行,没有阻塞当前线程。
  3. 任务按顺序执行,因为主队列时串行队列。

结语

本篇博客篇幅较长,但这只是 GCD 的入门介绍。事实上,我们讨论的内容还算基础,仅涉及了队列和任务的创建,以及它们如何组合在一起工作。然而,掌握这些基础概念是深入理解 GCD 并有效应用其强大功能的第一步。

未来还有更多复杂的机制和高级用法等待我们探索。希望通过这篇文章,你对 GCD 有了初步的认识,以后的博客我们会继续探讨GCD以及其它并发编程相关的内容。

这篇关于并发编程 - GCD的任务和队列的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1117617

相关文章

SpringBoot集成XXL-JOB实现任务管理全流程

《SpringBoot集成XXL-JOB实现任务管理全流程》XXL-JOB是一款轻量级分布式任务调度平台,功能丰富、界面简洁、易于扩展,本文介绍如何通过SpringBoot项目,使用RestTempl... 目录一、前言二、项目结构简述三、Maven 依赖四、Controller 代码详解五、Service

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

AOP编程的基本概念与idea编辑器的配合体验过程

《AOP编程的基本概念与idea编辑器的配合体验过程》文章简要介绍了AOP基础概念,包括Before/Around通知、PointCut切入点、Advice通知体、JoinPoint连接点等,说明它们... 目录BeforeAroundAdvise — 通知PointCut — 切入点Acpect — 切面

Spring Security 前后端分离场景下的会话并发管理

《SpringSecurity前后端分离场景下的会话并发管理》本文介绍了在前后端分离架构下实现SpringSecurity会话并发管理的问题,传统Web开发中只需简单配置sessionManage... 目录背景分析传统 web 开发中的 sessionManagement 入口ConcurrentSess

Python Flask实现定时任务的不同方法详解

《PythonFlask实现定时任务的不同方法详解》在Flask中实现定时任务,最常用的方法是使用APScheduler库,本文将提供一个完整的解决方案,有需要的小伙伴可以跟随小编一起学习一下... 目录完js整实现方案代码解释1. 依赖安装2. 核心组件3. 任务类型4. 任务管理5. 持久化存储生产环境

C#异步编程ConfigureAwait的使用小结

《C#异步编程ConfigureAwait的使用小结》本文介绍了异步编程在GUI和服务器端应用的优势,详细的介绍了async和await的关键作用,通过实例解析了在UI线程正确使用await.Conf... 异步编程是并发的一种形式,它有两大好处:对于面向终端用户的GUI程序,提高了响应能力对于服务器端应

MySQL中处理数据的并发一致性的实现示例

《MySQL中处理数据的并发一致性的实现示例》在MySQL中处理数据的并发一致性是确保多个用户或应用程序同时访问和修改数据库时,不会导致数据冲突、数据丢失或数据不一致,MySQL通过事务和锁机制来管理... 目录一、事务(Transactions)1. 事务控制语句二、锁(Locks)1. 锁类型2. 锁粒

深入解析Java NIO在高并发场景下的性能优化实践指南

《深入解析JavaNIO在高并发场景下的性能优化实践指南》随着互联网业务不断演进,对高并发、低延时网络服务的需求日益增长,本文将深入解析JavaNIO在高并发场景下的性能优化方法,希望对大家有所帮助... 目录简介一、技术背景与应用场景二、核心原理深入分析2.1 Selector多路复用2.2 Buffer

C# async await 异步编程实现机制详解

《C#asyncawait异步编程实现机制详解》async/await是C#5.0引入的语法糖,它基于**状态机(StateMachine)**模式实现,将异步方法转换为编译器生成的状态机类,本... 目录一、async/await 异步编程实现机制1.1 核心概念1.2 编译器转换过程1.3 关键组件解析