编程进阶网 编程进阶网
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接

杨充

专注编程 · 终身学习者
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接
  • README
  • Android提升进阶

  • iOS开发和进阶

    • README
    • ObjC编程入门

    • Swift编程入门

    • iOS入门到精通

      • iOS入门到精通案例
      • UIKit框架原理探索
      • UIViewController
      • 项目工程面板说明
      • 通信实践和设计思想
      • 网络请求和数据解析
      • 多线程实践和原理
        • 01.多线程基础概念
          • 1.1 多线程的概念
          • 1.2 Thread的创建
        • 02.多线程分类
          • 2.1 串⾏队列
          • 2.2 并行队列
          • 2.3 GCD的好处
        • 03.DispatchQueue实践
          • 3.1 主线程更新UI
          • 3.2 后台线程做任务
          • 3.3 串行和并发队列
          • 3.4 同步和异步任务
        • 04.OperationQueue实践
          • 4.1 添加操作到队列
          • 4.2 控制并发度
          • 4.3 按指定顺序执行
          • 4.4 取消任务执行
        • 05.其他一些多线程
          • 5.1 DispatchGroup使用
          • 10.参考博客文章
      • Swift和OC混编开发
      • Swift版SnapKit布局
      • 开发SDK实践设计
      • iOS经验类笔记积累
  • Web开发和进阶

  • Linux应用开发

  • Apps
  • iOS开发和进阶
  • iOS入门到精通
杨充
2025-02-26
目录

多线程实践和原理

# 14.多线程实践和原理

# 目录介绍

  • 01.多线程基础概念
    • 1.1 多线程的概念
    • 1.2 Thread的创建
    • 1.3 线程属性和方法
  • 02.多线程GCD说明
    • 2.1 串⾏队列
    • 2.2 并行队列
    • 2.3 GCD的好处
  • 03.DispatchQueue实践
    • 3.1 主线程更新UI
    • 3.2 后台线程做任务
    • 3.3 串行和并发队列
    • 3.4 同步和异步任务
  • 04.OperationQueue实践
    • 4.1 添加操作到队列
    • 4.2 控制并发度
    • 4.3 按指定顺序执行
    • 4.4 取消任务执行
  • 05.其他一些多线程
    • 5.1 DispatchGroup使用
  • 10.参考博客文章

# 01.多线程基础概念

# 1.1 多线程的概念

举个例子, 我们的程序运行, 都是按照代码从上往下的执行, 但如果遇到需要下载图片的时候, 它就会卡在这里, 等待图片下载完成才会执行下一步, 这样子就不符合我们的实际体验了, 所以我们会把下载图片放到子线程里去操作, 等到下载完成之后才传回给主线程, 这就是多线程的好处, 既不会影响主线程的运行, 又可以完成下载图片的任务.

提示:

  1. dispatch_async 异步操作,会并发执⾏,无法确定任务的执⾏顺序
  2. dispatch_sync 同步操作,会依次顺序执⾏,能够决定任务的执行顺序

PS: 线程是有限的, 不可以无休止的增加, 而主线程的大小只有1MB, 子线程都是512KB.

# 1.2 Thread的创建

可以使用 Thread 类来创建和使用线程。以下是使用 Thread 的一般步骤:

1.创建线程:

let myThread = Thread(target: self, selector: #selector(runThread), object: nil)
1

2.实现线程方法:实现了一个名为 runThread 的方法,用于在线程中执行任务。请注意,方法需要使用 @objc 标记,并且没有参数。

@objc func runThread() {
// 在线程中执行任务。可以做一些耗时操作
}
1
2
3

3.启动线程:

myThread.start()
1

然后测试一下案例,如下所示:

let thread1 = Thread(target: self, selector: #selector(threadMethod1), object: nil)
let thread2 = Thread {
    print("thread2 \(Thread.current)")
}
thread1.start()
thread2.start()

//通过类方法开辟的两个子线程,不返回Thread对象,创建后即就绪状态,无需start()方法。
Thread.detachNewThreadSelector(#selector(threadMethod3), toTarget: self, with: nil)
Thread.detachNewThread {
    print("thread4 \(Thread.current)")
}

//打印数据如下
thread1 <NSThread: 0x60000171e540>{number = 11, name = (null)}
thread3 <NSThread: 0x60000176e380>{number = 13, name = (null)}
thread4 <NSThread: 0x60000174f180>{number = 14, name = (null)}
thread2 <NSThread: 0x60000171d440>{number = 12, name = (null)}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 02.多线程分类

# 2.1 串⾏队列

  1. 同步任务, 不需要新建线程, 异步任务, 需要⼀个⼦线程, 线程的创建和回收不需要程序员参与!
  2. “是最安全的一个选择”串⾏行队列只能创建!

# 2.2 并行队列

同步任务, 不需要创建线程并行队列, 异步任务, 有多少个任务, 就开N个线程执⾏行 无论什么队列和什么任务, 线程的创建和回收不需要程序员参与.

线程的创建回收⼯作是由队列负责的 “并发”编程, 为了让程序员从负责的线程控制中解脱出来! 只需要⾯对队列和任务!

# 2.3 GCD的好处

通过GCD, 开发者不⽤再直接跟线程打交道, 只需要向队列中添加代码块即可。

GCD在后端管理着⼀个线程池, GCD不仅决定着代码块将在哪个线程被执⾏, 它还根据可用的系统资源对这些线程进⾏管理. 从而让开发者从线程管理的工作中解放出来, 通过集中的管理线程, 缓解大量线程被创建的问题。

使⽤用GCD, 开发者可以将工作考虑为一个队列, 而不是一堆线程,这种并行的抽象模型更容易掌握和使⽤.

GCD的队列

  1. GCD公开有5个不同的队列: 运⾏在主线程中的主队列,3个不同优先级的后台队列,以及一个优先级更低的后台队列(⽤于 I/O).
  2. ⾃定义队列: 串⾏行和并⾏行队列,⾃定义队列⾮常强大,建议在开发中使⽤,在⾃定义队列中被调度的所有Block最终都将被放⼊到系统的全局队列中和线程池中。

提示: 不建议使⽤用不同优先级的队列, 因为如果设计不当, 可能会出现优先级反转, 即低优先级的操作阻塞⾼优先级的操作.

GCD(Grand Central Dispatch ):https://www.jianshu.com/p/2d57c72016c6

# 03.DispatchQueue实践

# 3.1 主线程更新UI

1.在主线程上更新UI:使用DispatchQueue.main.async将UI操作封装在闭包中,以确保在主线程上执行。例如:

DispatchQueue.main.async {
// 在主线程上执行UI操作
}
1
2
3

# 3.2 后台线程做任务

2.在后台线程上执行任务:使用DispatchQueue.global执行耗时的任务,以避免阻塞主线程。您可以选择使用不同的QoS(Quality of Service)来指定任务的优先级。例如:

DispatchQueue.global(qos: .background).async {
// 在后台线程上执行任务
}
1
2
3

# 3.3 串行和并发队列

3.串行队列和并发队列:使用DispatchQueue来创建串行队列和并发队列,以控制任务的执行方式。例如:

// 创建串行队列
let serialQueue = DispatchQueue(label: "com.example.serialQueue")

// 创建并发队列
let concurrentQueue = DispatchQueue(label: "com.example.concurrentQueue", attributes: .concurrent)
1
2
3
4
5

# 3.4 同步和异步任务

4.同步和异步任务: 使用DispatchQueue.sync执行同步任务,该任务会阻塞当前线程,直到任务完成。使用DispatchQueue.async执行异步任务,该任务会在后台线程上执行,不会阻塞当前线程。例如:

// 同步任务
DispatchQueue.main.sync {
    // 执行同步任务
}

// 异步任务
DispatchQueue.global().async {
    // 执行异步任务
}
1
2
3
4
5
6
7
8
9

# 04.OperationQueue实践

OperationQueue是在iOS中进行多线程编程的另一个强大工具。以下是一些使用OperationQueue的技巧:

# 4.1 添加操作到队列

1.添加操作到队列:使用addOperation方法将操作添加到OperationQueue中。例如:

OperationQueue.main.addOperation { // 执行操作的代码 }

# 4.2 控制并发度

2.控制并发度:OperationQueue具有maxConcurrentOperationCount属性,用于控制队列中同时执行的操作数量。默认情况下,该值为-1,表示没有限制。您可以根据需要设置并发度。例如:

let operationQueue = OperationQueue.main;
operationQueue.maxConcurrentOperationCount = 2 // 最多同时执行2个操作
1
2

# 4.3 按指定顺序执行

3.添加依赖关系:使用addDependency方法为操作添加依赖关系,以确保操作按照指定的顺序执行。例如:

let operationQueue = OperationQueue.main;
let operation1 = BlockOperation {
    print("操作1的代码")
}

let operation2 = BlockOperation {
    print("操作2的代码")
}
operation2.addDependency(operation1) // 操作2依赖于操作1
operationQueue.addOperations([operation1,operation2], waitUntilFinished: false)
1
2
3
4
5
6
7
8
9
10

# 4.4 取消任务执行

4.取消操作:使用cancel方法取消操作的执行。取消操作后,它将不再执行。例如:

let operation = BlockOperation {
// 操作的代码
}

operation.cancel() // 取消操作
1
2
3
4
5

# 05.其他一些多线程

# 5.1 DispatchGroup使用

DispatchGroup 是一个用于管理多个异步任务的工具。它可以让你等待一组任务完成后再执行其他操作。

let group = DispatchGroup()

// 将任务添加到 DispatchGroup
group.enter()
someAsyncTask1 {
// 任务完成后离开 DispatchGroup
group.leave()
}

group.enter()
someAsyncTask2 {
// 任务完成后离开 DispatchGroup
group.leave()
}

// 等待 DispatchGroup 中的任务完成
group.notify(queue: .main) {
// 所有任务完成后执行的操作
print("所有任务已完成")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

首先创建了一个 DispatchGroup 对象 group。然后,我们使用 enter() 方法将任务添加到 DispatchGroup 中。在每个异步任务完成后,我们使用 leave() 方法离开 DispatchGroup。

最后,我们使用 notify(queue:execute:) 方法来等待 DispatchGroup 中的所有任务完成。当所有任务完成后,指定的闭包将在指定的队列(这里是主队列)上执行。

# 10.参考博客文章

Swift版本 1.多线程开发 -- CGD的简单使用:https://www.cnblogs.com/iOSCain/p/4529333.html Swift版本 2.多线程开发 -- NSOperation的简单使用:https://www.cnblogs.com/iOSCain/p/4529332.html Swift版本 3.多线程开发 -- Run Loop:https://www.cnblogs.com/iOSCain/p/4529331.html

上次更新: 2026/06/10, 11:13:41
网络请求和数据解析
Swift和OC混编开发

← 网络请求和数据解析 Swift和OC混编开发→

最近更新
01
信号崩溃快速排查
06-15
02
CoreDump破案
06-15
03
perf火焰图实战
06-15
更多文章>
Theme by Vdoing | Copyright © 2019-2026 杨充 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式