多线程包含三个元素:线程、任务、队列。GCD和OperationQueue会自动管理线程。
1. 线程负责任务调度。移动开发中主要有主线程和其他线程。
2. 任务就是需要执行的内容,是一段具有某些功能的代码或代码块。任务分为同步和异步两种,同步任务是在当前线程顺序执行,异步任务会开启新线程并不会等待完成就开始其他任务。
dispatch_async(queue, ^{
NSLog(@"同步任务");
});
dispatch_sync(queue, ^{
NSLog(@"异步任务");
});
//其中queue参数可以是自己创建的队列或获取全局队列、主队列。
3. 队列具有先进先出原则,但是在多线程调度过程中,队列中的任务执行顺序也受优先级影响。队列分为并行队列和串行队列。并行队列就是相同优先级的任务分别在不同的新线程中同时执行,串行队列是相同优先级的任务在一个新线程中顺序执行。
可以获取已存在的队列(全局队列、主队列)
dispatch_get_global_queue(0, 0)
dispatch_get_main_queue()
或者自己创建队列
dispatch_queue_create("com.plan.testqueue", DISPATCH_QUEUE_CONCURRENT);
/*
参数1:标记名称
参数2:队列类型(同步、异步)
1. 同步异步和并发队列串行队列组合使用
同步任务 + 并发队列 = 不开启新线程 + 在当前线程执行 + 顺序执行
NSLog(@"当前线程%@",[NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("com.plan.test", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
NSLog(@"任务1线程 : %@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"任务2线程 : %@",[NSThread currentThread]);
});
同步任务 + 串行队列 = 不开启新线程 + 在当前线程执行 + 顺序执行
NSLog(@"当前线程%@",[NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("com.plan.test", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"任务1线程 : %@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"任务2线程 : %@",[NSThread currentThread]);
});
同步任务 + 主队列 = 主线程执行 + 死锁
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"任务1");
});
//死锁:不会打印结果
异步任务 + 并发队列 = 开启多个新线程 + 同步执行
dispatch_queue_t queue = dispatch_queue_create("com.plan.test", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"任务1线程 : %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任务2线程 : %@",[NSThread currentThread]);
});
异步任务 + 串行队列 = 开启一个新线程 + 顺序执行
dispatch_queue_t queue = dispatch_queue_create("com.plan.test", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"任务1线程 : %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任务2线程 : %@",[NSThread currentThread]);
});
异步任务 + 主队列 = 主线程执行 + 任务低优先级 + 异步任务会在线程闲置时执行 + 顺序执行
特别注意的是主队列在加入同步任务的时候回产生死锁。主队列加入的异步任务会具有很低的优先级,比如:有5个直接调用任务,在其中通过GCD加入异步任务1和异步任务2到主队列,无论任务1和任务2在何时加入都会在其他5个任务执行结束后执行,而任务1和任务2的执行顺序对应加入顺序。
- (void)mainQueueTest
{
NSLog(@"任务a");
NSLog(@"任务b");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务2");
});
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务3");
});
NSLog(@"任务c");
NSLog(@"任务d");
NSLog(@"%@",[self longTimeTask]);
}
- (NSString *)longTimeTask
{
sleep(2);
return @"任务e";
}
结果: