iOS多线程

进程(Process)

进程是指在系统中正在运行的一个应用程序,比如同时打开微信和 QQ,系统会分别至少启动 2 个进程。每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。进程是系统进行资源分配和调度的一个独立单位。

注意

一个应用程序至少有一个进程,但不是说只有一个进程。

线程(Thread)

线程是某一个进程中一个单独运行的程序。线程是进程的一个实体。线程是 CPU 调度和分派的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源,但是它与同属一个进程的其他线程共享进程所拥有的全部资源。也就是线程存在于进程之中,一个进程由一个或多个线程构成,各线程之间共享相同的代码和全局数据,但各自有自己的堆栈。

一个程序有且只有一个主线程,与用户交互相关的中断性操作都会派发到主线程,程序启动时创建(调用main来启动),主线程的生命周期是和应用程序绑定,程序退出时,主线程也停止。

真正在应用程序中做任务的是线程。

任务(Task)

是指由应用程序完成的一个活动。一个任务既可以是一个进程,也可以是一个线程。任务是一系列为达到某一共同目的的操作集合。

进程和线程的区别和联系

  • 线程是CPU和资源调度(执行任务)的基本单位,是程序执行的最小单元,进程是资源分配和调度的基本单位。
  • 一个程序可以有多个进程,一个进程可以有多个线程,但至少要有一个线程,而一个线程只能属于一个进程。
  • 同一个进程内的线程共享进程的所有资源。

1. NSThread(最底层)

特点

  • 手动管理:需要开发者自行创建、启动和管理线程的生命周期。
  • 轻量级:直接操作线程,适合简单场景。
  • 可控性高:可以设置线程优先级、名称等属性。
  • 缺点:频繁创建线程开销大,需手动处理线程同步问题(如加锁)。

示例

let thread = Thread(target: self, selector: #selector(task), object: nil)
thread.start()

适用场景:需要精细控制线程行为的场景(较少使用)。

2. GCD(Grand Central Dispatch)(推荐)

特点

  • 基于队列的任务调度:通过队列(Queue)管理任务,自动处理线程生命周期。
  • 高效简洁:使用 Block 或闭包封装任务,避免手动管理线程。
  • 任务类型
    • 同步执行sync):阻塞当前线程,直到任务完成。
    • 异步执行async):不阻塞当前线程。
  • 队列类型
    • 串行队列(Serial Queue):任务按顺序执行。
    • 并发队列(Concurrent Queue):任务并行执行。
    • 主队列(Main Queue):串行队列,专用于更新 UI。
    • 全局队列(Global Queue):系统提供的并发队列。

示例

// 异步执行
DispatchQueue.global(qos: .background).async {
    // 后台任务
    DispatchQueue.main.async {
        // 回到主线程更新 UI
    }
}

高级功能

  • Dispatch Group:管理多个任务的完成状态。
  • Dispatch Semaphore:控制并发数量(如资源竞争)。
  • Barrier(屏障任务):确保读写安全。
  • Dispatch Source:监听事件(如定时器、文件读写)。

适用场景:绝大多数异步任务,如网络请求、耗时计算。

3. NSOperation 和 NSOperationQueue(基于 GCD 的高级封装)

特点

  • 面向对象:任务被封装为 NSOperation 对象(如 NSBlockOperation)。
  • 功能丰富
    • 任务依赖:通过 addDependency 设置执行顺序。
    • 取消任务:支持取消单个或所有任务(cancel())。
    • 队列控制:设置最大并发数、暂停/恢复队列。
  • 与 GCD 的区别
    • 更高抽象:适合复杂任务管理(如批量下载)。
    • 可控性更强:支持 KVO 监听任务状态。

示例

let operationQueue = OperationQueue()
operationQueue.maxConcurrentOperationCount = 2 // 最大并发数

let op1 = BlockOperation { /* 任务1 */ }
let op2 = BlockOperation { /* 任务2 */ }
op2.addDependency(op1) // op2 在 op1 完成后执行

operationQueue.addOperations([op1, op2], waitUntilFinished: false)

适用场景:需要任务依赖、取消或复杂调度的场景(如文件分片上传)。

三种方式的对比

特性NSThreadGCDNSOperation
抽象层级底层(直接操作线程)中层(队列管理任务)高层(面向对象)
线程生命周期管理手动管理自动管理自动管理
任务依赖不支持需手动实现(如 Barrier)原生支持
任务取消需手动实现不支持原生支持
性能较高高(C 语言 API)略低于 GCD(对象开销)
适用场景简单任务/精细控制线程常见异步任务复杂任务依赖/批量操作

在 iOS 中,NSOperationNSOperationQueue 是基于 GCD 的面向对象的高级封装,它们通过抽象化的方式将多线程任务的管理变得更加灵活和可控。以下是它们的核心封装内容:


1. NSOperation 的封装:任务对象化

NSOperation 将“任务”抽象成一个对象(面向对象思想),开发者可以通过子类化或使用系统提供的子类(如 NSBlockOperation)来定义任务。它的封装包括:

(1)任务封装
  • 任务本身:将代码逻辑封装为一个独立的对象(NSOperation 实例)。
  • 任务状态:内部维护了 isReadyisExecutingisFinishedisCancelled 等状态(通过 KVO 监听)。
  • 任务优先级:通过 queuePriority 属性设置优先级(veryLowlownormalhighveryHigh)。
  • 依赖关系:通过 addDependency(_ op: NSOperation) 添加依赖,确保任务按顺序执行。
(2)系统提供的子类
  • NSBlockOperation:用闭包(Block)封装任务,支持添加多个闭包(并行执行)。
    let blockOperation = BlockOperation {
        print("Task 1")
    }
    blockOperation.addExecutionBlock {
        print("Task 2")
    }
    
  • NSInvocationOperation(已废弃):通过方法调用封装任务(Swift 中不可用)。
(3)自定义 NSOperation

通过继承 NSOperation 创建自定义任务,需手动管理任务状态:

class CustomOperation: Operation {
    override func main() {
        guard !isCancelled else { return }
        // 任务逻辑
    }
}

2. NSOperationQueue 的封装:队列管理

NSOperationQueue 负责管理和调度 NSOperation 任务,封装了线程池、任务调度等底层逻辑,核心功能包括:

(1)自动线程管理
  • 基于 GCD:底层使用 GCD 的队列,但通过对象化的方式隐藏了线程细节。
  • 线程复用:自动管理线程的创建、复用和销毁,开发者无需手动操作线程。
(2)队列控制
  • 最大并发数:通过 maxConcurrentOperationCount 控制并发任务数(设为 1 可模拟串行队列)。
  • 队列暂停/恢复:通过 isSuspended 属性控制队列是否暂停执行新任务。
  • 取消所有任务:通过 cancelAllOperations() 一键取消队列中所有任务。
(3)任务调度
  • 依赖管理:自动处理任务之间的依赖关系,确保依赖任务完成后才执行后续任务。
  • 优先级调整:结合任务的 queuePriority 和队列的调度策略,动态调整执行顺序。

3. 与 GCD 相比的封装优势

NSOperationNSOperationQueue 在 GCD 的基础上,通过面向对象的方式提供了更高层次的抽象,解决了 GCD 的以下痛点:

(1)任务依赖
  • GCD:需手动通过 DispatchGroupDispatchSemaphoreBarrier 实现依赖。
  • NSOperation:直接通过 addDependency 声明依赖关系,代码更清晰。
    let op1 = BlockOperation { /* 任务A */ }
    let op2 = BlockOperation { /* 任务B */ }
    op2.addDependency(op1) // op2 依赖 op1
    queue.addOperations([op1, op2], waitUntilFinished: false)
    
(2)任务取消
  • GCD:提交到队列的任务无法取消(除非未开始执行)。
  • NSOperation:通过 cancel() 方法取消单个任务,或通过 cancelAllOperations() 取消队列中所有任务。
    let operation = BlockOperation { /* 耗时任务 */ }
    queue.addOperation(operation)
    operation.cancel() // 取消任务(若未执行)
    
(3)任务状态监听
  • GCD:无原生状态监听机制。
  • NSOperation:支持通过 KVO 监听 isFinishedisCancelled 等状态。
    operation.addObserver(self, forKeyPath: "isFinished", options: .new, context: nil)
    
(4)复杂任务管理
  • 并发控制:通过 maxConcurrentOperationCount 限制并发数(如最多 3 个下载任务)。
  • 优先级调整:动态调整任务的优先级,适应业务需求变化。

4. 底层实现与 GCD 的关系

  • NSOperationQueue 底层依赖 GCDNSOperationQueue 的线程池和任务调度最终由 GCD 的队列(如 DispatchQueue)实现。
  • 更高层次的抽象NSOperation 封装了 GCD 的 DispatchWorkItem,并添加了状态管理、依赖等逻辑。

5. 适用场景示例

  1. 批量下载:限制最大并发数,避免同时下载过多文件。
  2. 任务依赖:先下载数据,再解析数据,最后更新 UI。
  3. 可取消任务:用户离开页面时取消所有未完成的任务。
  4. 动态优先级:用户手动调整某个任务的优先级(如优先下载某个文件)。

总结

NSOperationNSOperationQueue 的封装本质是:

  • 将任务对象化:通过 NSOperation 抽象任务,使其具备状态、依赖、优先级等属性。
  • 将队列智能化:通过 NSOperationQueue 管理任务调度,隐藏底层线程细节,提供高级控制功能。

这种封装让开发者更专注于业务逻辑,而非多线程的底层实现,尤其适合需要精细控制任务流程的复杂场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值