GCD(Grand Central Dispatch)
优点:
>1.利用多核进行并行运算
>2.自动充分使用设备的CPU内核
>3.自动管理线程的生命周期(线程创建、线程调度、线程销毁)
两种任务(执行的block):
1.同步(dispatch_sync):在当前线程中执行,不能开启新线程,按顺序执行。
2.异步(dispatch_async):具备开启新线程的能力,但不一定会开启新线程,可不用等待继续执行。
两种队列(Dispatch Queue):
1.串行队列(Serial Dispatch Queue):每次只执行一个任务,按顺序执行。
2.并发队列(Concurrent Dispatch Queue):多个任务并发执行。并发队列的并发功能只有在异步(dispatch_async)才开启新线程。
系统默认提供两种队列:
主队列:dispatch_get_main_queue() -------- 不可以使用dispatch_sync这个block执行 不死锁卡死。
全局队列:
第一个参数表示队列优先级,一般用DISPATCH_QUEUE_PRIORITY_DEFAULT。第二个参数暂时没用,用0
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)
异步(async)➕主队列dispatch_get_main_queue(), 不会开启新线程,在主队列中执行任务。
异步(async)+串行队列(Serial),开启一条新线程串行执行。
异步(async)+并发队列(Concurrent),开启新线程,并发执行任务。
同步(sync)➕主队列dispatch_get_main_queue(),锁死。
同步(sync)+串行队列(Serial),没有开启新线程,串行执行任务。
同步(sync)+并发队列(Concurrent),没有开启新线程,在当前线程中串行执行任务。
>同步不具备开启新线程的能力,串行是按顺序执行的,所以只有异步+并发才开启多条线程,异步+串行会开一条串行执行,其他同步相关的都不会开启新线程。
栅栏方法---
dispatch_async(queue, ^{
for(inti =0; i <2; i++) {
NSLog(@"1------%@",[NSThreadcurrentThread]);
}
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(20);
// 这个异步不受 dispatch_barrier_async 和 dispatch_barrier_sync 的控制,
NSLog(@"5------%@",[NSThreadcurrentThread]);
});
});
dispatch_async(queue, ^{
for(inti =0; i <2; i++) {
NSLog(@"2------%@",[NSThreadcurrentThread]);
}
});
dispatch_barrier_async(queue, ^{
sleep(5);
NSLog(@"--异步--barrier-----%@", [NSThread currentThread]);
// aa 先打印 所以 异步的 barrier会先执行后面的任务(先插入后面的队列) 再执行自己的任务
});
NSLog(@"aa, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
for(inti =0; i <2; i++) {
NSLog(@"3------%@",[NSThreadcurrentThread]);
}
});
dispatch_barrier_sync(queue, ^{
sleep(5);
NSLog(@"--同步--barrier-----%@", [NSThread currentThread]);
// bb cc 后打印 所以 同步的 barrier会执行完自己的任务再执行后面的任务
});
NSLog(@"bb, %@", [NSThread currentThread]);
dispatch_async(queue, ^{
for(inti =0; i <2; i++) {
NSLog(@"4------%@",[NSThreadcurrentThread]);
}
});
NSLog(@"cc, %@", [NSThread currentThread]);
// 2021-12-29 15:32:53.877454+0800 test[26026:3577219] aa, {number = 1, name = main}
// 2021-12-29 15:32:53.877455+0800 test[26026:3577373] 1------{number = 3, name = (null)}
// 2021-12-29 15:32:53.877570+0800 test[26026:3577372] 2------{number = 4, name = (null)}
// 2021-12-29 15:32:53.877589+0800 test[26026:3577373] 1------{number = 3, name = (null)}
// 2021-12-29 15:32:53.877622+0800 test[26026:3577372] 2------{number = 4, name = (null)}
// 2021-12-29 15:32:58.883172+0800 test[26026:3577372] --异步--barrier-----{number = 4, name = (null)}
// 2021-12-29 15:32:58.884079+0800 test[26026:3577372] 3------{number = 4, name = (null)}
// 2021-12-29 15:32:58.884514+0800 test[26026:3577372] 3------{number = 4, name = (null)}
// 2021-12-29 15:33:03.886208+0800 test[26026:3577219] --同步--barrier-----{number = 1, name = main}
// 2021-12-29 15:33:03.886802+0800 test[26026:3577219] bb, {number = 1, name = main}
// 2021-12-29 15:33:03.887395+0800 test[26026:3577219] cc, {number = 1, name = main}
// 2021-12-29 15:33:03.887629+0800 test[26026:3577372] 4------{number = 4, name = (null)}
// 2021-12-29 15:33:03.888017+0800 test[26026:3577372] 4------{number = 4, name = (null)}
// 2021-12-29 15:33:13.883409+0800 test[26026:3577373] 5------{number = 3, name = (null)}
GCD队列组(dispatch_group)
dispatch_group_notify
监听group中的任务执行结束后 通知 dispatch_group_notify 处理任务。(等待多个耗时异步任务完成后执行新的任务)
// DISPATCH_QUEUE_CONCURRENT 并发 async 异步 可开启多条新线程
dispatch_queue_t queue= dispatch_queue_create("net.test.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
//
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
for(inti =0; i <2; i++) {
NSLog(@"1------%@",[NSThreadcurrentThread]);
}
// 这个异步 不受单独的 notify控制 模拟 AFNetworking的网络请求,需要配合 enter和leave 它俩成对出现,如果只写 enter 没有写leave dispatch_group_notify就一直不会被调用,如果只写leave 不写enter 会崩溃
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(10);
NSLog(@"5------%@",[NSThreadcurrentThread]);
dispatch_group_leave(group);
});
});
dispatch_group_async(group, queue, ^{
for(inti =0; i <2; i++) {
NSLog(@"2------%@",[NSThreadcurrentThread]);
}
});
dispatch_group_async(group, queue, ^{
for(inti =0; i <2; i++) {
NSLog(@"3------%@",[NSThreadcurrentThread]);
}
});
dispatch_group_notify(group, queue, ^{
NSLog(@"end------%@",[NSThread currentThread]);
});
// 2021-12-29 15:44:07.865654+0800 test[26044:3581038] 1------{number = 3, name = (null)}
// 2021-12-29 15:44:07.865830+0800 test[26044:3581037] 2------{number = 6, name = (null)}
// 2021-12-29 15:44:07.865912+0800 test[26044:3581037] 2------{number = 6, name = (null)}
// 2021-12-29 15:44:07.866085+0800 test[26044:3581039] 3------{number = 4, name = (null)}
// 2021-12-29 15:44:07.866090+0800 test[26044:3581038] 1------{number = 3, name = (null)}
// 2021-12-29 15:44:07.866282+0800 test[26044:3581039] 3------{number = 4, name = (null)}
// 2021-12-29 15:44:17.872043+0800 test[26044:3581038] 5------{number = 3, name = (null)}
// 2021-12-29 15:44:17.872754+0800 test[26044:3581038] end------{number = 3, name = (null)}
GCD 的信号量(Semaphore)
->持有计数的信号。判断信号量count是否大于0,大于0继续执行同时信号量-1进入等待
// DISPATCH_QUEUE_CONCURRENT 并发 async 异步 可开启多条新线程
dispatch_queue_t queue= dispatch_queue_create("net.test.queue", DISPATCH_QUEUE_CONCURRENT);
// >=0 可通过
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); //semaphore = 1 可以用作串行 或者加锁。大于 1 例如 2 可控制并发数量
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//semaphore - 1
NSLog(@"1--start----%@",[NSThread currentThread]);
sleep(1);
NSLog(@"1---end---%@",[NSThread currentThread]);
// 这个异步模拟 AFNetworking的网络请求,
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"5--start----%@",[NSThreadcurrentThread]);
sleep(10);
NSLog(@"5---end---%@",[NSThreadcurrentThread]);
dispatch_semaphore_signal(semaphore);//semaphore + 1
});
});
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//semaphore - 1
NSLog(@"2---start---%@",[NSThread currentThread]);
sleep(1);
NSLog(@"2---end---%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore); //semaphore + 1
});
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//semaphore - 1
NSLog(@"3---start---%@",[NSThread currentThread]);
sleep(1);
NSLog(@"3---end---%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore); //semaphore + 1
});
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//semaphore - 1
NSLog(@"4---start---%@",[NSThread currentThread]);
sleep(1);
NSLog(@"4---end---%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore); //semaphore + 1
});
//
// 2021-12-29 16:12:50.430879+0800 test[26123:3593064] 1--start----{number = 4, name = (null)}
// 2021-12-29 16:12:51.452075+0800 test[26123:3593064] 1---end---{number = 4, name = (null)}
// 2021-12-29 16:12:51.452460+0800 test[26123:3593064] 5--start----{number = 4, name = (null)}
// 2021-12-29 16:13:01.458350+0800 test[26123:3593064] 5---end---{number = 4, name = (null)}
// 2021-12-29 16:13:01.459085+0800 test[26123:3593062] 2---start---{number = 3, name = (null)}
// 2021-12-29 16:13:02.464750+0800 test[26123:3593062] 2---end---{number = 3, name = (null)}
// 2021-12-29 16:13:02.465406+0800 test[26123:3593070] 3---start---{number = 10, name = (null)}
// 2021-12-29 16:13:03.470995+0800 test[26123:3593070] 3---end---{number = 10, name = (null)}
// 2021-12-29 16:13:03.471634+0800 test[26123:3593065] 4---start---{number = 11, name = (null)}
// 2021-12-29 16:13:04.477316+0800 test[26123:3593065] 4---end---{number = 11, name = (null)}
group+semaphore可实现异步顺序调用
// DISPATCH_QUEUE_CONCURRENT 并发 async 异步 可开启多条新线程
dispatch_queue_t queue= dispatch_queue_create("net.test.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
// >=0 可通过
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); //semaphore = 1 可以用作串行 或者加锁。大于 1 例如 2 可控制并发数量
dispatch_group_async(group, queue, ^{
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//semaphore - 1
NSLog(@"1--start----%@",[NSThread currentThread]);
sleep(1);
NSLog(@"1---end---%@",[NSThread currentThread]);
// 这个异步模拟 AFNetworking的网络请求,
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"5--start----%@",[NSThreadcurrentThread]);
sleep(10);
NSLog(@"5---end---%@",[NSThreadcurrentThread]);
dispatch_semaphore_signal(semaphore);//semaphore + 1
});
});
dispatch_group_async(group, queue, ^{
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//semaphore - 1
NSLog(@"2---start---%@",[NSThread currentThread]);
sleep(1);
NSLog(@"2---end---%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore); //semaphore + 1
});
dispatch_group_async(group, queue, ^{
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//semaphore - 1
NSLog(@"3---start---%@",[NSThread currentThread]);
sleep(1);
NSLog(@"3---end---%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore); //semaphore + 1
});
dispatch_group_async(group, queue, ^{
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//semaphore - 1
NSLog(@"4---start---%@",[NSThread currentThread]);
sleep(1);
NSLog(@"4---end---%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore); //semaphore + 1
});
dispatch_group_notify(group, queue, ^{
NSLog(@"end------%@",[NSThread currentThread]);
});
// 2021-12-29 16:18:08.689161+0800 test[26127:3594185] 1--start----{number = 6, name = (null)}
// 2021-12-29 16:18:09.725393+0800 test[26127:3594185] 1---end---{number = 6, name = (null)}
// 2021-12-29 16:18:09.725805+0800 test[26127:3594192] 5--start----{number = 7, name = (null)}
// 2021-12-29 16:18:19.731812+0800 test[26127:3594192] 5---end---{number = 7, name = (null)}
// 2021-12-29 16:18:19.732540+0800 test[26127:3594186] 2---start---{number = 5, name = (null)}
// 2021-12-29 16:18:20.738224+0800 test[26127:3594186] 2---end---{number = 5, name = (null)}
// 2021-12-29 16:18:20.738990+0800 test[26127:3594191] 3---start---{number = 11, name = (null)}
// 2021-12-29 16:18:21.744409+0800 test[26127:3594191] 3---end---{number = 11, name = (null)}
// 2021-12-29 16:18:21.745058+0800 test[26127:3594183] 4---start---{number = 3, name = (null)}
// 2021-12-29 16:18:22.746883+0800 test[26127:3594183] 4---end---{number = 3, name = (null)}
// 2021-12-29 16:18:22.747554+0800 test[26127:3594183] end------{number = 3, name = (null)}