刚在掘金上发现了一个系列文章,写的挺好。
侵删:掘金多线程系列文章
技术方案 | 简介 | 语言 | 生命周期 | 使用频率 |
---|---|---|---|---|
pthread | 一套通用的多线程 API 适用于 Unix/linux/Windows 等系统 跨平台/可移植 使用难度大 |
C | 程序员管理 | 几乎不用 |
NSThread | 使用更加面向对象 简单易用,可直接操作线程对象 |
OC | 程序员管理 | 偶尔使用 |
GCD | 旨在替代 NSThread 等线程技术 | C | 自动管理 | 经常使用 |
NSOperation | 基于GCD(底层是GCD) 比 GCD 多了一些更加简单实用的功能 使用更加面向对象 |
OC | 自动管理 | 经常使用 |
pthread
无
NSThread
- 3种创建方式
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(task) object:nil];
[thread start];
[NSThread detachNewThreadSelector:@selector(task) toTarget:self withObject:nil];
[self performSelector:@selector(task) withObject:nil];
常用属性
thread.name = @"线程1";
thread.threadPriority = 0;@synchronized 互斥锁 (买票问题)
-
assign 与 weak 的区别
assign 的对象释放后,指针变成野指针,调用对象的方法会崩溃
weak 的对象释放后,指针指向 0 地址,调用对象的方法不会崩溃 -
为什么 controller 中的 view 使用 weak,不是 strong
因为 self.view 中的 subviews 包含 controller 中的所有 view ,而这个引用是强引用,所以 controller 没必要对 view 再加一次强引用。否则就是对一个 view 做了两次强引用,不利于内存管理。错误实例
self.imageView = [[UIImageView alloc] init];
self.imageView 会是 nil。因为没有对象对 [[UIImageView alloc] init] 进行强引用,在 ARC 模式下刚创建就自动释放了。
正确写法UIImageView *imageView = [[UIImageView alloc] init]; self.imageView = imageView;
消息循环
- 主线程的消息循环默认是开启的,子线程默认不开启
- 创建 NSTimer 添加到 runloop 中, 设置 mode
- nstimer 的mode 和 消息循环的mode 相同的时候,timer 才能执行。(拖动文本框的例子)
- 开启子线程的 runloop 的3种方法
GCD
- 基本使用(异步下载图片的改写)
task,queen,dispatch - 各种队列
方式 | 全局并行队列 | 并发队列 | 串行队列 | 主队列 |
---|---|---|---|---|
同步(sync) | 不开启新线程 串行执行 |
不开新线程 串行执行 |
不开启新线程 串行执行 |
死锁 |
异步(async) | 开启新线程 并行执行 |
开多个线程(个数 gcd 觉得) 并发执行 |
开启一个新线程 串行执行 |
不开启新线程 串行执行 |
- GCD 练习
任务1,2在子线程执行
完成之后通知主线程执行任务3,4并顺序执行
完成之后开启任务5,6,7并发执行
-
延迟执行
NSTimer performSelector dispatch_after
-
队列组
场景:首先:分别异步执行2个耗时的操作 其次:等2个异步操作都执行完毕后,再回到主线程执行操作
关键词:dispatch_group_create,dispatch_group_async, dispatch_group_notify
-
一次性执行
xcode 会代码提示static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@"dispatch_once"); });
单例模式(2种)