串行队列(Serial Queue)和并行队列(Concurre

2025-03-18  本文已影响0人  山水域

串行队列(Serial Queue)和并行队列(Concurrent Queue)详解并代码示例。内容主要基于 DispatchQueue,是 Grand Central Dispatch (GCD) 的核心组件,用于管理多线程任务。


1. 串行队列 (Serial Queue)

概念

创建方法

let serialQueue = DispatchQueue(label: "com.qrlink.serial")

使用方法

代码示例与注解

import UIKit

class SerialQueueExample {
    // 创建一个串行队列
    private let serialQueue = DispatchQueue(label: "com.qrlink.serialQueue")
    
    func performTasks() {
        // 任务 1: 异步执行
        serialQueue.async {
            print("Task 1 started at \(Date())")
            Thread.sleep(forTimeInterval: 2) // 模拟耗时操作
            print("Task 1 finished at \(Date())")
        }
        
        // 任务 2: 异步执行
        serialQueue.async {
            print("Task 2 started at \(Date())")
            Thread.sleep(forTimeInterval: 1) // 模拟耗时操作
            print("Task 2 finished at \(Date())")
        }
        
        // 任务 3: 同步执行
        serialQueue.sync {
            print("Task 3 started at \(Date())")
            Thread.sleep(forTimeInterval: 1) // 模拟耗时操作
            print("Task 3 finished at \(Date())")
        }
        
        print("Main thread continues at \(Date())")
    }
}

// 测试代码
let example = SerialQueueExample()
example.performTasks()

输出示例:

Main thread continues at 2025-03-18 10:00:00 +0000
Task 1 started at 2025-03-18 10:00:00 +0000
Task 1 finished at 2025-03-18 10:00:02 +0000
Task 2 started at 2025-03-18 10:00:02 +0000
Task 2 finished at 2025-03-18 10:00:03 +0000
Task 3 started at 2025-03-18 10:00:03 +0000
Task 3 finished at 2025-03-18 10:00:04 +0000

注解:


2. 并行队列 (Concurrent Queue)

概念

创建方法

let concurrentQueue = DispatchQueue(label: "com.qrlink.concurrent", attributes: .concurrent)

全局并行队列

使用方法

代码示例与注解

import UIKit

class ConcurrentQueueExample {
    // 创建一个自定义并行队列
    private let concurrentQueue = DispatchQueue(label: "com.qrlink.concurrentQueue", attributes: .concurrent)
    
    // 使用全局并行队列
    private let globalQueue = DispatchQueue.global(qos: .userInitiated)
    
    func performTasks() {
        // 任务 1: 异步执行
        concurrentQueue.async {
            print("Task 1 started at \(Date()) on \(Thread.current)")
            Thread.sleep(forTimeInterval: 2)
            print("Task 1 finished at \(Date())")
        }
        
        // 任务 2: 异步执行
        concurrentQueue.async {
            print("Task 2 started at \(Date()) on \(Thread.current)")
            Thread.sleep(forTimeInterval: 1)
            print("Task 2 finished at \(Date())")
        }
        
        // 任务 3: 使用栅栏,确保前面的任务完成后执行
        concurrentQueue.async(flags: .barrier) {
            print("Barrier Task started at \(Date())")
            Thread.sleep(forTimeInterval: 1)
            print("Barrier Task finished at \(Date())")
        }
        
        // 任务 4: 在全局队列执行
        globalQueue.async {
            print("Global Task started at \(Date())")
            Thread.sleep(forTimeInterval: 1)
            print("Global Task finished at \(Date())")
        }
        
        print("Main thread continues at \(Date())")
    }
}

// 测试代码
let example = ConcurrentQueueExample()
example.performTasks()

输出示例:

Main thread continues at 2025-03-18 10:00:00 +0000
Task 1 started at 2025-03-18 10:00:00 +0000 on <NSThread: 0x...>{number = 2}
Task 2 started at 2025-03-18 10:00:00 +0000 on <NSThread: 0x...>{number = 3}
Global Task started at 2025-03-18 10:00:00 +0000 on <NSThread: 0x...>{number = 4}
Task 2 finished at 2025-03-18 10:00:01 +0000
Global Task finished at 2025-03-18 10:00:01 +0000
Task 1 finished at 2025-03-18 10:00:02 +0000
Barrier Task started at 2025-03-18 10:00:02 +0000
Barrier Task finished at 2025-03-18 10:00:03 +0000

注解:


3. 串行队列 vs 并行队列

特性 串行队列 并行队列
执行顺序 按顺序(FIFO) 并行,无序
并发性 单任务执行 多任务同时执行
线程安全 天然线程安全 需手动同步(如使用栅栏)
创建方式 DispatchQueue(label:) DispatchQueue(label:, attributes: .concurrent)
典型场景 顺序操作、资源保护 独立任务、高并发

4. 方法与参数详解

DispatchQueue 方法

  1. sync(execute:)

    • 意义: 同步执行任务,阻塞当前线程直到任务完成。
    • 参数: execute: 一个闭包,包含要执行的任务。
    • 使用方法: 用于需要立即获取结果的场景,但避免在主线程使用耗时操作。
    • 示例:
      serialQueue.sync {
          print("Sync task on serial queue")
      }
      
  2. async(execute:)

    • 意义: 异步执行任务,不阻塞当前线程。
    • 参数: execute: 一个闭包,包含要执行的任务。
    • 使用方法: 适合耗时操作,常见于后台任务。
    • 示例:
      concurrentQueue.async {
          print("Async task on concurrent queue")
      }
      
  3. async(flags: .barrier, execute:)

    • 意义: 在并行队列中添加栅栏任务,确保前面的任务完成后执行。
    • 参数:
      • flags: .barrier: 指定栅栏属性。
      • execute: 栅栏任务闭包。
    • 使用方法: 用于并行队列中的同步点,例如写操作。
    • 示例:
      concurrentQueue.async(flags: .barrier) {
          print("Barrier task")
      }
      

DispatchQueue 参数


5. 综合应用示例

结合摄像头扫描场景,展示串行和并行队列的使用:

class CameraQueueExample {
    private let serialQueue = DispatchQueue(label: "com.qrlink.serialCamera")
    private let concurrentQueue = DispatchQueue(label: "com.qrlink.concurrentCamera", attributes: .concurrent)
    private var captureSession: AVCaptureSession?
    
    func setupCamera() {
        captureSession = AVCaptureSession()
        guard let captureSession = captureSession else { return }
        
        // 串行队列:顺序配置摄像头
        serialQueue.async {
            guard let device = AVCaptureDevice.default(for: .video) else { return }
            do {
                let input = try AVCaptureDeviceInput(device: device)
                captureSession.beginConfiguration()
                captureSession.addInput(input)
                
                let output = AVCaptureMetadataOutput()
                captureSession.addOutput(output)
                captureSession.commitConfiguration()
                
                // 并行队列:同时启动会话和处理其他任务
                self.concurrentQueue.async {
                    captureSession.startRunning()
                    print("Camera started at \(Date())")
                }
                
                self.concurrentQueue.async {
                    print("Other task started at \(Date())")
                    Thread.sleep(forTimeInterval: 1)
                    print("Other task finished at \(Date())")
                }
                
                // 栅栏:确保会话启动后再执行
                self.concurrentQueue.async(flags: .barrier) {
                    print("Barrier task after camera setup at \(Date())")
                }
            } catch {
                print("Setup failed: \(error)")
            }
        }
    }
}

let cameraExample = CameraQueueExample()
cameraExample.setupCamera()

输出示例:

Camera started at 2025-03-18 10:00:00 +0000
Other task started at 2025-03-18 10:00:00 +0000
Other task finished at 2025-03-18 10:00:01 +0000
Barrier task after camera setup at 2025-03-18 10:00:01 +0000

注解:

上一篇 下一篇

猜你喜欢

热点阅读