在GCD多线程的学习中,我发现了dispatch_set_target_queue这个函数。
在官方文档的释义中:https://developer.apple.com/documentation/dispatch/1452989-dispatch_set_target_queue?language=occ
对象的目标队列负责处理对象。目标队列确定调用对象终结器的队列。此外,修改一些对象的目标队列会改变它们的行为:
分派队列的优先级从其目标队列继承。使用dispatch_get_global_queue函数获得所需优先级的合适目标队列。
如果您将一个块提交给一个串行队列,而串行队列的目标队列是一个不同的串行队列,那么该块不会与提交给目标队列或具有相同目标队列的任何其他队列的块并发调用。
根据以上释义,我们可以了解到dispatch_set_target_queue可以有这两个作用:
第一:变更队列的执行优先级;
第二:目标队列可以成为原队列的执行阶层。
好的,接下来我们用代码来验证加深印象
一:变更队列的执行优先级
dispatch_queue_t q1 = dispatch_queue_create("q1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q2 = dispatch_queue_create("q2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q3 = dispatch_queue_create("q3", DISPATCH_QUEUE_SERIAL);
dispatch_async(q1, ^{
NSLog(@"1");
});
dispatch_async(q2, ^{
NSLog(@"2");
});
dispatch_async(q3, ^{
NSLog(@"3");
});
这时代码运行输出是 1 2 3无序输出的
2019-03-26 11:52:34.281356+0800 Target[95936:2409849] 3
2019-03-26 11:52:34.281356+0800 Target[95936:2409841] 1
2019-03-26 11:52:34.281356+0800 Target[95936:2409843] 2
----------------------------------------------------------------
2019-03-26 11:54:44.154362+0800 Target[95970:2411026] 2
2019-03-26 11:54:44.154362+0800 Target[95970:2411023] 1
2019-03-26 11:54:44.154362+0800 Target[95970:2411025] 3
我们给其中q1加一个后台targetqueue,看看结果如何
dispatch_queue_t q1 = dispatch_queue_create("q1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q2 = dispatch_queue_create("q2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q3 = dispatch_queue_create("q3", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(q1, globalQueue);
dispatch_async(q1, ^{
NSLog(@"1");
});
dispatch_async(q2, ^{
NSLog(@"2");
});
dispatch_async(q3, ^{
NSLog(@"3");
});
这是输出结果(注:GCD并不能完全保证优先级高的任务一定先执行):
2019-03-26 11:57:14.369213+0800 Target[96036:2412962] 3
2019-03-26 11:57:14.369213+0800 Target[96036:2412960] 2
2019-03-26 11:57:14.369245+0800 Target[96036:2412963] 1
---------------------------------------------------------------
2019-03-26 11:58:50.073760+0800 Target[96061:2413923] 2
2019-03-26 11:58:50.073760+0800 Target[96061:2413921] 3
2019-03-26 11:58:50.073788+0800 Target[96061:2413922] 1
从结果可以看出,q1的目标队列是优先级低的后台队列,所以最终q1的执行在最后,也验证了dispatch_set_target_queue可以修改队列的执行优先级。
二:目标队列可以成为原队列的执行阶层。
dispatch_queue_t q1 = dispatch_queue_create("q1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q2 = dispatch_queue_create("q2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q3 = dispatch_queue_create("q3", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q4 = dispatch_queue_create("q3", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q5 = dispatch_queue_create("q3", DISPATCH_QUEUE_SERIAL);
dispatch_async(q1, ^{
NSLog(@"1");
});
dispatch_async(q2, ^{
NSLog(@"2");
});
dispatch_async(q3, ^{
NSLog(@"3");
});
dispatch_async(q4, ^{
NSLog(@"4");
});
dispatch_async(q5, ^{
NSLog(@"5");
});
我们创建5个串行队列,并在这些串行队列中异步执行,输出一个数,这个时候输出结果是这样的:
2019-03-26 11:37:17.384915+0800 Target[95606:2398987] 1
2019-03-26 11:37:17.384915+0800 Target[95606:2398986] 5
2019-03-26 11:37:17.384936+0800 Target[95606:2398988] 3
2019-03-26 11:37:17.384964+0800 Target[95606:2398989] 2
2019-03-26 11:37:17.385006+0800 Target[95606:2398995] 4
也就是乱序,并发执行的。
我们在其中加入一个串行的目标队列如下:
dispatch_queue_t q1 = dispatch_queue_create("q1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q2 = dispatch_queue_create("q2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q3 = dispatch_queue_create("q3", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q4 = dispatch_queue_create("q4", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q5 = dispatch_queue_create("q5", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t targetQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(q1, targetQueue);
dispatch_set_target_queue(q2, targetQueue);
dispatch_set_target_queue(q3, targetQueue);
dispatch_set_target_queue(q4, targetQueue);
dispatch_set_target_queue(q5, targetQueue);
dispatch_async(q1, ^{
NSLog(@"1");
});
dispatch_async(q2, ^{
NSLog(@"2");
});
dispatch_async(q3, ^{
NSLog(@"3");
});
dispatch_async(q4, ^{
NSLog(@"4");
});
dispatch_async(q5, ^{
NSLog(@"5");
});
输出结果如下:
2019-03-26 12:03:47.953843+0800 Target[96144:2416455] 1
2019-03-26 12:03:47.954033+0800 Target[96144:2416455] 2
2019-03-26 12:03:47.954148+0800 Target[96144:2416455] 3
2019-03-26 12:03:47.954420+0800 Target[96144:2416455] 4
2019-03-26 12:03:47.955926+0800 Target[96144:2416455] 5
这样就变得有序了,从这里可以看出,串行目标队列成为了那5个队列的执行阶层。(其实第一第二个例子都是能够证明一和二的),并使队列里的任务变得有序,即串行执行。我们在实际开发中可以使用这种技术避免并发执行。
注:若将目标队列targetQueue修改为并发队列,则不会有什么实际的效果,还是并发执行
dispatch_queue_t targetQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_CONCURRENT);
2019-03-26 12:09:31.225278+0800 Target[96247:2419291] 1
2019-03-26 12:09:31.225280+0800 Target[96247:2419290] 3
2019-03-26 12:09:31.225281+0800 Target[96247:2419289] 4
2019-03-26 12:09:31.225307+0800 Target[96247:2419292] 2
2019-03-26 12:09:31.225469+0800 Target[96247:2419290] 5