Foundation — Thread

官方文档

通义 #

以下是关于 Foundation 框架中 Thread 模块的详细介绍:

1. Thread 模块简介 #

Thread 是 Foundation 框架中的一个核心模块,用于处理多线程编程。它允许开发者在 macOS 和 iOS 等 Apple 平台上创建、管理和操作线程,从而实现并发执行任务。


2. 主要 API 分类 #

(1)线程管理相关 API #

  • init(target:selector:object:)
    • 创建一个新的线程并指定目标对象、方法和参数。
    • 示例:
      let thread = Thread(target: self, selector: #selector(runTask), object: nil)
      thread.start()
      
  • start()
    • 启动线程。
  • main()
    • 定义线程的主要执行逻辑(如果未使用 init(target:selector:object:) 初始化)。
  • cancel()
    • 取消线程的执行。
  • isCancelled
    • 检查线程是否已被取消。

(2)线程状态相关 API #

  • isExecuting
    • 判断线程是否正在运行。
  • isFinished
    • 判断线程是否已完成。
  • isMainThread
    • 判断当前线程是否是主线程。

(3)线程优先级相关 API #

  • threadPriority
    • 获取或设置线程的优先级(范围:0.0 到 1.0,默认值为 0.5)。
    • 示例:
      thread.threadPriority = 0.7
      

(4)线程同步相关 API #

  • detachNewThreadSelector(_:toTarget:with:)
    • 在后台线程中异步执行指定的选择器方法。
  • sleep(forTimeInterval:)
    • 让当前线程休眠一段时间。
    • 示例:
      Thread.sleep(forTimeInterval: 2.0) // 线程休眠 2 秒
      

3. 使用场景 #

  • 后台任务处理
    • 将耗时操作(如网络请求、文件读写)放到后台线程中,避免阻塞主线程。
  • 任务并发
    • 使用多个线程同时执行多个任务以提高效率。
  • 线程同步
    • 在多线程环境中确保数据的一致性和安全性。

4. 如何使用 Thread #

示例代码:创建并启动一个线程 #

class MyTask {
    @objc func runTask() {
        print("子线程开始执行")
        Thread.sleep(forTimeInterval: 2.0) // 模拟耗时操作
        print("子线程结束执行")
    }
}

let myTask = MyTask()
let thread = Thread(target: myTask, selector: #selector(MyTask.runTask), object: nil)
thread.start()

示例代码:检查线程状态 #

let thread = Thread {
    print("线程正在运行")
}
thread.start()

if thread.isExecuting {
    print("线程正在执行")
}
if thread.isFinished {
    print("线程已结束")
}

示例代码:设置线程优先级 #

let highPriorityThread = Thread {
    print("高优先级线程")
}
highPriorityThread.threadPriority = 0.9
highPriorityThread.start()

5. 注意事项 #

  • 避免阻塞主线程
    • 主线程负责 UI 更新,任何耗时操作都应放在后台线程中。
  • 线程安全
    • 在多线程环境下访问共享资源时,需要使用锁或其他同步机制避免竞争条件。
  • GCD 的推荐
    • 在现代开发中,推荐使用 Grand Central Dispatch (GCD) 或 OperationQueue 来替代 Thread,因为它们更高效且易于管理。

希望以上内容对你有所帮助!

Deepseek #

Foundation 框架中的 Thread 类为多线程编程提供了底层支持,允许开发者直接管理线程的生命周期和执行逻辑。以下是按功能分类的详细介绍,涵盖核心 API、使用场景、示例代码及注意事项。


一、线程的创建与启动 #

1. 显式创建线程对象 #

  • API
    // 初始化方式 1:通过 Target-Action 模式
    init(target: Any, selector: Selector, object: Any?)
    
    // 初始化方式 2:通过闭包
    init(block: @escaping () -> Void)
    
  • 使用场景:需要手动控制线程的生命周期(如启动、取消、配置属性)。
  • 示例
    // 方式 1:Target-Action
    let thread1 = Thread(target: self, selector: #selector(backgroundTask), object: nil)
    thread1.start()
    
    // 方式 2:闭包
    let thread2 = Thread {
        print("Thread running in background")
    }
    thread2.start()
    

2. 隐式创建并自动启动 #

  • API
    class func detachNewThreadSelector(_ selector: Selector, toTarget target: Any, with argument: Any?)
    class func detachNewThread(with block: @escaping () -> Void)
    
  • 使用场景:快速启动后台线程,无需手动管理线程对象。
  • 示例
    // 启动一个立即执行的线程
    Thread.detachNewThread {
        print("Detached thread started")
    }
    

二、线程配置 #

1. 优先级与服务质量 #

  • API
    var qualityOfService: QualityOfService  // 线程优先级(替代已废弃的 threadPriority)
    
  • 使用场景:调整线程执行优先级(如用户交互、后台任务)。
  • 示例
    let thread = Thread {
        // 高优先级任务(如 UI 相关预处理)
    }
    thread.qualityOfService = .userInteractive
    thread.start()
    

2. 线程命名与堆栈大小 #

  • API
    var name: String?       // 线程名称(调试用)
    var stackSize: Int      // 堆栈大小(字节)
    
  • 示例
    let thread = Thread { /* ... */ }
    thread.name = "NetworkRequestThread"
    thread.stackSize = 1024 * 1024 * 2  // 2MB 堆栈
    

三、线程状态控制 #

1. 启动与取消 #

  • API
    func start()            // 启动线程
    func cancel()           // 标记线程为取消状态
    var isCancelled: Bool   // 检查是否被取消
    
  • 使用场景:安全终止长时间运行的任务。
  • 示例
    class CustomThread: Thread {
        override func main() {
            while !isCancelled {
                print("Working...")
                Thread.sleep(forTimeInterval: 1)
            }
        }
    }
    
    let thread = CustomThread()
    thread.start()
    // 5秒后取消线程
    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        thread.cancel()
    }
    

2. 线程休眠 #

  • API
    class func sleep(forTimeInterval ti: TimeInterval)
    class func sleep(until date: Date)
    
  • 示例
    // 当前线程休眠 3 秒
    Thread.sleep(forTimeInterval: 3)
    

四、主线程操作 #

1. 主线程判断与跳转 #

  • API
    class var isMainThread: Bool    // 当前是否为主线程
    class var main: Thread          // 获取主线程对象
    
  • 使用场景:确保 UI 更新在主线程执行。
  • 示例
    DispatchQueue.global().async {
        // 后台任务...
        if !Thread.isMainThread {
            DispatchQueue.main.async {
                self.label.text = "Updated on main thread"
            }
        }
    }
    

2. 主线程同步执行 #

  • API
    func perform(onMainThread aSelector: Selector, with arg: Any?, waitUntilDone wait: Bool)
    
  • 示例
    // 在后台线程中更新 UI
    Thread.detachNewThread {
        // 后台操作...
        self.perform(#selector(self.updateUI), on: Thread.main, with: nil, waitUntilDone: true)
    }
    

五、线程间通信 #

1. 跨线程方法调用 #

  • API
    func perform(_ aSelector: Selector, on thr: Thread, with arg: Any?, waitUntilDone wait: Bool)
    
  • 示例
    let workerThread = Thread {
        Thread.current.name = "WorkerThread"
        RunLoop.current.run()  // 保持线程存活
    }
    workerThread.start()
    
    // 在主线程调用 workerThread 的方法
    self.perform(#selector(doWork), on: workerThread, with: nil, waitUntilDone: false)
    

六、线程本地存储 #

1. 存储线程私有数据 #

  • API
    var threadDictionary: NSMutableDictionary { get }
    
  • 使用场景:保存线程特定的上下文信息(如用户会话、临时缓存)。
  • 示例
    Thread.current.threadDictionary["requestID"] = "12345"
    

七、调试与诊断 #

1. 获取调用栈信息 #

  • API
    class var callStackSymbols: [String]     // 当前调用栈符号
    class var callStackReturnAddresses: [NSNumber]  // 返回地址
    
  • 示例
    print(Thread.callStackSymbols.joined(separator: "\n"))
    

使用注意事项 #

  1. 避免直接管理线程:优先使用 GCDOperationQueue,它们更高效且不易出错。
  2. 线程安全
    • 使用 NSLockNSCondition@synchronized 保护共享资源。
    • 避免在非主线程操作 UI。
  3. 资源管理
    • 确保线程在完成任务后释放资源。
    • 使用 autoreleasepool 包裹线程任务(尤其在处理大量临时对象时)。
  4. RunLoop 集成
    • 若需线程长期存活并处理事件(如网络监听),需手动启动 RunLoop:
      Thread.detachNewThread {
          RunLoop.current.add(Port(), forMode: .default)
          RunLoop.current.run()
      }
      

完整示例:后台下载 + 主线程回调 #

class DownloadManager: NSObject {
    func startDownload(url: URL) {
        let downloadThread = Thread(target: self, selector: #selector(downloadTask(_:)), object: url)
        downloadThread.name = "DownloadThread"
        downloadThread.start()
    }

    @objc func downloadTask(_ url: URL) {
        autoreleasepool {
            // 模拟下载耗时操作
            let data = try! Data(contentsOf: url)
            // 回到主线程处理结果
            perform(#selector(handleDownloadResult(_:)), on: Thread.main, with: data, waitUntilDone: false)
        }
    }

    @objc func handleDownloadResult(_ data: Data) {
        print("Downloaded data size: \(data.count)")
    }
}

与 GCD 的对比 #

特性ThreadGCD
控制粒度精细(直接操作线程)抽象(队列管理)
性能开销较高(需手动管理)较低(系统优化)
适用场景需要底层控制的复杂任务常规并发任务(推荐优先使用)
内存管理需手动处理 RunLoop 和资源自动管理

通过合理选择 Thread 或更高层次的并发工具,可以平衡代码复杂性与性能需求。

本文共 2179 字,创建于 Feb 22, 2025
相关标签: Xcode, Swift, Foundation