pthread
- 一套通用的多线程API,适用于Unix/Linux/Windows等系统,跨平台/可移植
- 使用难度大
- 基于C语言
- 由
程序员管理
线程生命周期 - 几乎不用
NSThread
- 使用更加面向对象
- 简单易用,可直接操作线程对象
- 基于OC语言
- 由
程序员管理
线程生命周期 - 偶尔使用
GCD
- 旨在替代NSThread等线程技术
- 充分利用设备的多核
- 基于C语言
自动管理
线程生命周期- 经常使用
queue
队列:用来存放任务,将需要执行的任务添加到队列中,队列会遵循FIFO原则(先进先出、后进后出),将队列中的任务取出,放到对应的线程中执行
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
# DISPATCH_QUEUE_SERIAL 串行队列
# DISPATCH_QUEUE_CONCURRENT 并行队列
dispatch_queue_t queue = dispatch_queue_create("队列标签", DISPATCH_QUEUE_SERIAL);
同步/异步
同步:立即执行任务
异步:延迟执行任务
dispatch_sync(queue, ^{
});
dispatch_async(queue, ^{
});
主队列同步任务:
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
}
});
NSLog(@"step 2 %@", [NSThread currentThread]);
线程死锁,应用崩溃
主队列异步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"async 1_%d %@", i, [NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"async 2_%d %@", i, [NSThread currentThread]);
}
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 2_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 2_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 2_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 2_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 2_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
- 异步任务被延后执行
- 异步任务在主线程下执行
全局队列同步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
}
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
- 同步任务被立即执行
- 同步任务在主线程下执行
全局队列异步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"async 1_%d %@", i, [NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"async 2_%d %@", i, [NSThread currentThread]);
}
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_0 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_0 <NSThread: 0x600002f4c600>{number = 8, name = (null)}
async 2_1 <NSThread: 0x600002f4c600>{number = 8, name = (null)}
async 1_1 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_2 <NSThread: 0x600002f4c600>{number = 8, name = (null)}
async 1_2 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_3 <NSThread: 0x600002f4c600>{number = 8, name = (null)}
async 1_3 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_4 <NSThread: 0x600002f4c600>{number = 8, name = (null)}
async 1_4 <NSThread: 0x600002f46800>{number = 7, name = (null)}
- 异步任务被延后执行
- 异步任务在多个新的线程下执行
串行队列同步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("serial_queue_label", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
}
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
- 同步任务被立即执行
- 同步任务在主线程下执行
串行队列异步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("serial_queue_label", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"async 1_%d %@", i, [NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"async 2_%d %@", i, [NSThread currentThread]);
}
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_0 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 1_1 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 1_2 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 1_3 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 1_4 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_0 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_1 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_2 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_3 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_4 <NSThread: 0x600002f46800>{number = 7, name = (null)}
- 异步任务被延后执行
- 异步任务在一个新的线程下执行
并行队列同步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("concurrent_queue_label", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
}
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
- 同步任务被立即执行
- 同步任务在主线程下执行
并行队列异步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("concurrent_queue_label", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"async 1_%d %@", i, [NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"async 2_%d %@", i, [NSThread currentThread]);
}
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_0 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_0 <NSThread: 0x600002fb0c80>{number = 9, name = (null)}
async 1_1 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_1 <NSThread: 0x600002fb0c80>{number = 9, name = (null)}
async 1_2 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_2 <NSThread: 0x600002fb0c80>{number = 9, name = (null)}
async 1_3 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_3 <NSThread: 0x600002fb0c80>{number = 9, name = (null)}
async 1_4 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_4 <NSThread: 0x600002fb0c80>{number = 9, name = (null)}
- 异步任务被延后执行
- 异步任务在多个新的线程下执行
NSOperation
- 底层是GCD
- 比GCD多了一些更简单实用的功能
- 使用更加面向对象
- 基于OC语言
自动管理
线程生命周期- 经常使用
线程死锁
当前串行队列中,使用sync函数添加任务(立即执行任务),会卡住当前的串行队列(产生死锁)
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
}
});
NSLog(@"step 2 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("serial_queue_label", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 5; ++i) {
NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
}
});
NSLog(@"step 2 %@", [NSThread currentThread]);
});
死锁的执行流程:
- 串行队列中的任务1在线程中执行
- 线程中的任务1在执行中需要立即(sync)执行串行队列中的任务2
- 串行队列中的任务2必须在线程中的任务1执行完毕后,才能进入线程中执行
- 线程中的任务1必须立即执行任务2,才能执行完毕
- 死锁
解锁方法:
- 将任务分布到不同的队列中
- 将串行队列改为并行队列
- 将立即(sync)执行改为延迟(async)执行