GCD:是4.0新增的,C语言写的,他是苹果公司为多核CPU的并行运算提高效率出现的,能够自动管理线程的生命周期,不需要我们对线程的管理。
1.任务和队列
GCD的核心是任务和队列的概念
任务:分为同步任务sync顺序执行,异步任务async开启线成。
队列:串行队列 顺序执行, 并发队列 开启线程。
2.相关API
1).队列
全局主队列系统提供(串行)
dispatch_queue_t queue = dispatch_get_main_queue()
全局并发队列系统提供
/*参数一队列优先级
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台添加同步任务
参数二:队列名称 设为0就好
*/
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
自定义创建队列
/参数一:队列表示符0表示
参数二:队列类型
DISPATCH_QUEUE_SERIAL串行队列
DISPATCH_QUEUE_COUNNET 并行队列
/
dispatch_queue_t queue = dispatch_queue_creat(@“”,表示队列类型)
2).创建任务
同步任务
dispatch_sync(queue,^{
//代码
});
异步任务
dispatch_async(queue,^{
})
3.代码测试
1.同步+串行队列
//创建同步队列 SERIAL串行队列 COUNNET并发队列
dispatch_queue_t queue = dispatch_queue_create("name", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
//执行代码
for (NSInteger i=0; i<100; i++) {
NSLog(@"1--%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"2---%@",[NSThread currentThread]);
}
});
NSLog(@"结束回归主线程");
总结:同步+串行队列 只有一个条线程,不会开启新的线程。任务一个一个执行。
- 同步+并发
dispatch_queue_t queue1 = dispatch_queue_create("chuan", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue1, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"同步并发任务1---%@",[NSThread currentThread]);
}
});
dispatch_sync(queue1, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"同步并发任务2---%@",[NSThread currentThread]);
}
});
总结:同步+并发队列 不开启新线程,在主线程执行按顺序执行
3.异步+串行
//创建串行队列 serial串行
dispatch_queue_t queue2 = dispatch_queue_create("yibu", DISPATCH_QUEUE_SERIAL);
//创建异步任务
dispatch_async(queue2, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"异步串行任务1---%@",[NSThread currentThread]);
}
});
dispatch_async(queue2, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"异步串行任务2---%@",[NSThread currentThread]);
}
});
总结:异步任务+串行队列 会开启新线程,按顺序执行
4.异步任务+并行队列
//并发队列
dispatch_queue_t queue3 = dispatch_queue_create("yi", DISPATCH_QUEUE_CONCURRENT);
//异步任务
dispatch_async(queue3, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"异步并发任务1---%@",[NSThread currentThread]);
//延迟操作
[NSThread sleepForTimeInterval:3];
}
});
dispatch_async(queue3, ^{
for (NSInteger i=0; i<10; i++) {
NSLog(@"异步并发任务2---%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:5];
}
});
总结:异步任务+并行队列 会开启多条线程,任务同时执行,但是没有顺序,没有顺序,没有顺序
5.异步任务+并行队列 按顺序执行
需要使用栅栏函数
创建并行队列
dispatch_queue_t queuebirrer = dispatch_queue_create("birrer", DISPATCH_QUEUE_CONCURRENT);
//创建同步任务
dispatch_async(queuebirrer, ^{
for (NSInteger i=0; i<5; i++) {
// NSLog(@"异步并发任务1---%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
}
});
//创建栅栏函数
dispatch_barrier_async(queuebirrer, ^{
for (NSInteger i=0; i<5; i++) {
// NSLog(@"异步并发栅栏函数任务2---%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
}
});
总结:使用栅栏函数可以使 异步任务+并行队列按顺序执行
6.主队列(串行)+同步
dispatch_queue_t mainqueue = dispatch_get_main_queue(); //串行队列
dispatch_sync(mainqueue, ^{
for (int i = 0; i < 4; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"主队列+同步1---%@",[NSThread currentThread]);
}
});
dispatch_sync(mainqueue, ^{
for (int i = 0; i < 3; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"主队列+同步2---%@",[NSThread currentThread]);
}
});
总结: 同步任务+串行主队列 会堵塞主线程,程序崩溃,在其他线程不会奔溃
7.主队列+异步任务
dispatch_queue_t mainqueue = dispatch_get_main_queue(); //串行队列
dispatch_async(mainqueue, ^{
for (int i = 0; i < 4; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"主队列+异步1---%@",[NSThread currentThread]);
}
});
dispatch_async(mainqueue, ^{
for (int i = 0; i < 4; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"主队列+异步2---%@",[NSThread currentThread]);
}
});
总结:异步任务+主队列 不开启新线程,任务一个一个执行
8.线程间通信
线程间通信指的是子线程与主线程之间的通信
//全局并发队列
dispatch_queue_t globorqQueue = dispatch_get_global_queue(0, 0);
//主队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(globorqQueue, ^{
for (int i = 0; i <10; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"全局并发队列------%@",[NSThread currentThread]);
}
//回归主线程
dispatch_async(mainQueue, ^{
NSLog(@"线程执行完毕来兄弟告诉我执行玩了没,玩了我就刷新控件了");
});
});
9.延迟函数 dispatch_after
延迟2秒执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
});
10一次性函数 dispatch_once_t 经常用于创建单列
static dispatch_once_t onceKey;
dispatch_once(&onceKey, ^{
// manage = [[manage alloc]init];
});
11.队列组 dispatch_group 当子线程异步任务执行完毕后,回归主线程
//创建队列组
dispatch_group_t group = dispatch_group_create();
//创建全局并发队列
dispatch_queue_t gqueue = dispatch_get_global_queue(0, 0);
//调用异步队列组,参数一队列组,参数二全局并发队列
dispatch_group_async(group, gqueue, ^{
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"异步全局队列组任务1---%@",[NSThread currentThread]);
}
});
dispatch_group_async(group, gqueue, ^{
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"异步全局队列组任务2---%@",[NSThread currentThread]);
}
});
//上面任务执行完毕回到主线程:参数一:队列组,参数二全局主队列
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"好了你们子线程都执行完毕了该我主线程更新ui");
});
12.暂停线程 dispatch_wait 堵塞当前线程,等指定队列组任务执行完毕才会继续执行
dispatch_group_t wgroup = dispatch_group_create();
dispatch_queue_t wqueue = dispatch_get_global_queue(0, 0);
dispatch_group_async(wgroup,wqueue, ^{
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"异步全局队列组任务wait1---%@",[NSThread currentThread]);
}
});
dispatch_group_async(wgroup, wqueue, ^{
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"异步全局队列组任务wait 2---%@",[NSThread currentThread]);
}
});
//DISPATCH_TIME_NOW(即使上面的队列组中任务未完成也会执行下面的方法)
//DISPATCH_TIME_FOREVER 上面队列组任务执行完毕以后才会执行下面的方法
dispatch_group_wait(wgroup, DISPATCH_TIME_FOREVER);
NSLog(@"wait---上面执行完毕就是我了😄");
13.信号量dispatch_semaphore_t 主要作用解决线程同步的问题
个人理解当信号量大于1那么继续执行,小于1那么堵塞不执行
dispatch_semaphroe_signal和dispatch_semaphore_wait成对出现
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
__block int number = 10;
//全局并发队列
dispatch_queue_t queue9 = dispatch_get_global_queue(0, 0);
dispatch_async(queue9, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
for (int i = 0; i < 10; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"信号量---%@",[NSThread currentThread]);
}
number = 20;
//下面这个函数是当该线程执行完毕让线程的信号量+1执行下面的方法,当不添加这句的话会不走下面的函数
dispatch_semaphore_signal(semaphore);
});