GCD 串行队列,并行队列,同步执行,异步执行的探讨(附练习题)。
并行队列 + 异步执行
dispatch_queue_t queue = dispatch_queue_create("https://github.com/sunchengxiu", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"---start---");
dispatch_async(queue, ^{
NSLog(@"1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3---%@", [NSThread currentThread]);
});
NSLog(@"---end---");
2018-07-26 17:26:19.113262+0800 GCD[96770:11685014] ---start---
2018-07-26 17:26:19.113454+0800 GCD[96770:11685014] ---end---
2018-07-26 17:26:19.113625+0800 GCD[96770:11685190] 2---<NSThread: 0x60800026a380>{number = 4, name = (null)}
2018-07-26 17:26:19.113627+0800 GCD[96770:11685189] 1---<NSThread: 0x600000266f40>{number = 3, name = (null)}
2018-07-26 17:26:19.113631+0800 GCD[96770:11685187] 3---<NSThread: 0x604000078640>{number = 5, name = (null)}
原因
并行队列:
任务放在队列中后,依照FIFO的原则,从队列中取出任务,因为是并行队列,所以任务不需要排队,并发执行
异步执行:
可以开启新的线程。不需要按顺序执行
所以:
并行队列并发执行就会开启三个新的线程并且并发执行,这三个任务是同时执行的没有先后
串行队列 + 异步执行
dispatch_queue_t queue = dispatch_queue_create("https://github.com/sunchengxiu", DISPATCH_QUEUE_SERIAL);
NSLog(@"---start---");
dispatch_async(queue, ^{
NSLog(@"1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3---%@", [NSThread currentThread]);
});
NSLog(@"---end---");
2018-07-26 17:54:06.097899+0800 GCD[97224:11742559] ---start---
2018-07-26 17:54:06.098074+0800 GCD[97224:11742559] ---end---
2018-07-26 17:54:06.098161+0800 GCD[97224:11742839] 1---<NSThread: 0x6000002694c0>{number = 3, name = (null)}
2018-07-26 17:54:06.098329+0800 GCD[97224:11742839] 2---<NSThread: 0x6000002694c0>{number = 3, name = (null)}
2018-07-26 17:54:06.098495+0800 GCD[97224:11742839] 3---<NSThread: 0x6000002694c0>{number = 3, name = (null)}
原因
串行队列:
任务遵循FIFO,按照顺序执行
异步执行:
可以开启新的线程,可以先绕过不执行,一会执行
并发队列 + 同步执行
2018-07-26 17:56:58.266369+0800 GCD[97298:11752182] ---start---
2018-07-26 17:56:58.266563+0800 GCD[97298:11752182] 1---<NSThread: 0x6080000700c0>{number = 1, name = main}
2018-07-26 17:56:58.266747+0800 GCD[97298:11752182] 2---<NSThread: 0x6080000700c0>{number = 1, name = main}
2018-07-26 17:56:58.267059+0800 GCD[97298:11752182] 3---<NSThread: 0x6080000700c0>{number = 1, name = main}
2018-07-26 17:56:58.267153+0800 GCD[97298:11752182] ---end---
原因
同步执行:
不能开启新的线程,任务必须完成才可以往下走,只有当前线程这一个线程
并行队列:
因为这里是同步执行并且没有开启新的线程,所以任务没有办法分发到别的线程去执行,所以只能在当前线程按照顺序执行完
串行队列 + 同步执行
dispatch_queue_t queue = dispatch_queue_create("https://github.com/sunchengxiu", DISPATCH_QUEUE_SERIAL);
NSLog(@"---start---");
dispatch_sync(queue, ^{
NSLog(@"1---%@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2---%@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3---%@", [NSThread currentThread]);
});
NSLog(@"---end---");
2018-07-26 18:01:48.805460+0800 GCD[97421:11769974] ---start---
2018-07-26 18:01:48.805748+0800 GCD[97421:11769974] 1---<NSThread: 0x60c000068200>{number = 1, name = main}
2018-07-26 18:01:48.805899+0800 GCD[97421:11769974] 2---<NSThread: 0x60c000068200>{number = 1, name = main}
2018-07-26 18:01:48.806018+0800 GCD[97421:11769974] 3---<NSThread: 0x60c000068200>{number = 1, name = main}
2018-07-26 18:01:48.806118+0800 GCD[97421:11769974] ---end---
原因
串行队列:
任务按照队列顺序执行
同步执行:
不开启新的线程,在当前线程按照顺序执行
主队列 + 异步执行
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"---start---");
dispatch_async(queue, ^{
NSLog(@"任务1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任务2---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任务3---%@", [NSThread currentThread]);
});
NSLog(@"---end---");
2018-07-26 18:04:05.329334+0800 GCD[97491:11777882] ---start---
2018-07-26 18:04:05.329530+0800 GCD[97491:11777882] ---end---
2018-07-26 18:04:05.356499+0800 GCD[97491:11777882] 任务1---<NSThread: 0x600000074ac0>{number = 1, name = main}
2018-07-26 18:04:05.356681+0800 GCD[97491:11777882] 任务2---<NSThread: 0x600000074ac0>{number = 1, name = main}
2018-07-26 18:04:05.356857+0800 GCD[97491:11777882] 任务3---<NSThread: 0x600000074ac0>{number = 1, name = main}
原因
主队列:
任务一定是按顺序执行的,并且只能在主线程
异步执行:
可以开启新的线程,并且可以一会回来执行
所以:
因为不能在子线程,无法开启新的线程,所以只能在主线程按照顺序执行,但是可以回头过来执行
主队列 + 同步执行
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"---start---");
dispatch_sync(queue, ^{
NSLog(@"任务1---%@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"任务2---%@", [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"任务3---%@", [NSThread currentThread]);
});
NSLog(@"---end---");
死锁,程序卡死
原因
主队列的任务必须在主线程按照顺序执行,任务一要等待主队列的任务完成后才能执行,而主队列打印完end才算任务完成,他不想异步执行,可以等待别人执行完再过来执行,任务一等待朱队列打印完end才可以执行,而同步执行必须按照任务一个一个执行,执行完一个才可以执行下一个,所以任务一和打印end相互等待,造成死锁
练习1
dispatch_queue_t serialQueue = dispatch_queue_create("https://github.com/sunchengxiu", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
NSLog(@"0--%@",[NSThread currentThread]);
sleep(1);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"2--%@",[NSThread currentThread]);
sleep(1);
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
sleep(1);
NSLog(@"4--%@",[NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
NSLog(@"5--%@",[NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
NSLog(@"6--%@",[NSThread currentThread]);
});
2018-07-26 18:12:55.559756+0800 GCD[97708:11805558] 0--<NSThread: 0x604000273140>{number = 3, name = (null)}
2018-07-26 18:12:56.560263+0800 GCD[97708:11805558] 1--<NSThread: 0x604000273140>{number = 3, name = (null)}
2018-07-26 18:12:56.560455+0800 GCD[97708:11805558] 2--<NSThread: 0x604000273140>{number = 3, name = (null)}
2018-07-26 18:12:57.561658+0800 GCD[97708:11805558] 3--<NSThread: 0x604000273140>{number = 3, name = (null)}
2018-07-26 18:12:58.562398+0800 GCD[97708:11805444] 4--<NSThread: 0x60000006ddc0>{number = 1, name = main}
2018-07-26 18:12:58.562541+0800 GCD[97708:11805444] 5--<NSThread: 0x60000006ddc0>{number = 1, name = main}
2018-07-26 18:12:58.562668+0800 GCD[97708:11805444] 6--<NSThread: 0x60000006ddc0>{number = 1, name = main}
原因
串行队列:
任务按照入队列的顺序依次执行
异步执行
可以开启新的线程,在子线程中执行
同步执行
在当前线程中执行
所以:
上面组合的结果就是0,1,2,3可以开心新的线程在子线程中执行,但是需要按照顺序,4,5,6,只能在当前线程按照顺序执行
练习2
dispatch_queue_t serialQueue = dispatch_queue_create("https://github.com/sunchengxiu", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(serialQueue, ^{
NSLog(@"0--%@",[NSThread currentThread]);
sleep(1);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"2--%@",[NSThread currentThread]);
sleep(1);
NSLog(@"3--%@",[NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
sleep(1);
NSLog(@"4--%@",[NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
NSLog(@"5--%@",[NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
NSLog(@"6--%@",[NSThread currentThread]);
});
2018-07-26 18:19:19.042046+0800 GCD[97893:11823044] 0--<NSThread: 0x60400026ccc0>{number = 3, name = (null)}
2018-07-26 18:19:19.042046+0800 GCD[97893:11823045] 2--<NSThread: 0x60000027c0c0>{number = 4, name = (null)}
2018-07-26 18:19:20.043071+0800 GCD[97893:11822808] 4--<NSThread: 0x608000077440>{number = 1, name = main}
2018-07-26 18:19:20.043286+0800 GCD[97893:11822808] 5--<NSThread: 0x608000077440>{number = 1, name = main}
2018-07-26 18:19:20.043490+0800 GCD[97893:11822808] 6--<NSThread: 0x608000077440>{number = 1, name = main}
2018-07-26 18:19:20.047234+0800 GCD[97893:11823044] 1--<NSThread: 0x60400026ccc0>{number = 3, name = (null)}
2018-07-26 18:19:20.047504+0800 GCD[97893:11823045] 3--<NSThread: 0x60000027c0c0>{number = 4, name = (null)}
原因
并发队列:
可以从队列中取出所有的任务 ,然后并发执行
异步执行:
可以开启新的线程,并且不用等待任务执行再执行下一个任务
同步执行:
不具备开线程的能力,任务按照顺序执行
所以:
上面的0,1,2,3,任务不需要都执行玩才执行下面,可以执行完下面的任务再执行自己,0,2,的顺序可以不不一定,4,5,6的顺序必须是一样的,因为有延迟所以过了一面才会执行1,3,并且4,5,6都在当前的一个线程,0,1,2,3开辟了一个新的线程,在各自开辟的新县城里面执行自己的任务。
练习3
dispatch_queue_t serialQueue = dispatch_queue_create("https://github.com/sunchengxiu", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(serialQueue, ^{
NSLog(@"4--%@",[NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
NSLog(@"5--%@",[NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
NSLog(@"6--%@",[NSThread currentThread]);
sleep(3);
});
dispatch_async(serialQueue, ^{
NSLog(@"0--%@",[NSThread currentThread]);
sleep(1);
NSLog(@"1--%@",[NSThread currentThread]);
});
dispatch_async(serialQueue, ^{
NSLog(@"2--%@",[NSThread currentThread]);
sleep(1);
NSLog(@"3--%@",[NSThread currentThread]);
});
2018-07-26 18:25:01.444843+0800 GCD[98067:11840223] 4--<NSThread: 0x608000073140>{number = 1, name = main}
2018-07-26 18:25:01.445023+0800 GCD[98067:11840223] 5--<NSThread: 0x608000073140>{number = 1, name = main}
2018-07-26 18:25:01.445138+0800 GCD[98067:11840223] 6--<NSThread: 0x608000073140>{number = 1, name = main}
2018-07-26 18:25:01.445332+0800 GCD[98067:11840268] 0--<NSThread: 0x60c000262c00>{number = 3, name = (null)}
2018-07-26 18:25:01.445336+0800 GCD[98067:11840282] 2--<NSThread: 0x608000460800>{number = 4, name = (null)}
2018-07-26 18:25:02.448910+0800 GCD[98067:11840268] 1--<NSThread: 0x60c000262c00>{number = 3, name = (null)}
2018-07-26 18:25:02.448945+0800 GCD[98067:11840282] 3--<NSThread: 0x608000460800>{number = 4, name = (null)}
原因
这个例子和上面的例子代码相反,因为首先执行同步任务,所以任务4,5,6必须同时执行完才可以执行0,1,2,3