一个线程休眠时使用GCD的并发队列调度规则
Dispatch rule of concurrent queue using GCD when sleep in one thread
测试代码如下:
dispatch_queue_t queue = dispatch_queue_create("sc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:10];
NSLog(@"10s --- %@", [NSThread currentThread]);
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{
NSLog(@"First: 5s --- %@", [NSThread currentThread]);
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{
NSLog(@"Second: 5s --- %@", [NSThread currentThread]);
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{
NSLog(@"Third: 5s --- %@", [NSThread currentThread]);
});
这里我创建了一个并发队列,并使用异步方式休眠一个线程。
然而,输出是:
2016-03-26 12:17:57.164 TestPlayground[28188:551287] 10s --- <NSThread: 0x7fa080511730>{number = 2, name = (null)}
2016-03-26 12:17:57.165 TestPlayground[28188:551287] First: 5s --- <NSThread: 0x7fa080511730>{number = 2, name = (null)}
2016-03-26 12:17:57.166 TestPlayground[28188:551307] Second: 5s --- <NSThread: 0x7fa080704a80>{number = 3, name = (null)}
2016-03-26 12:17:57.166 TestPlayground[28188:551301] Third: 5s --- <NSThread: 0x7fa080511530>{number = 4, name = (null)}
GCD 似乎阻塞了第一个线程 10 秒,然后开始为并发工作创建新线程。
但是如果我只是将自建队列替换成全局并发队列,不改变下面的作业
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// ... same as before
输出更合理
2016-03-26 12:23:29.496 TestPlayground[28320:558467] First: 5s --- <NSThread: 0x7ff473c08b80>{number = 4, name = (null)}
2016-03-26 12:23:29.496 TestPlayground[28320:558483] Second: 5s --- <NSThread: 0x7ff473f18c50>{number = 2, name = (null)}
2016-03-26 12:23:29.496 TestPlayground[28320:558471] Third: 5s --- <NSThread: 0x7ff473d0a7c0>{number = 3, name = (null)}
2016-03-26 12:23:34.030 TestPlayground[28320:558456] 10s --- <NSThread: 0x7ff473e218e0>{number = 5, name = (null)}
GCD 中对此类作业的调度规则是什么?为什么自建并发队列和全局队列不一样?
如果我在睡眠作业前添加新作业
dispatch_queue_t queue = dispatch_queue_create("sc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{ NSLog(@"start --- %@", [NSThread currentThread]); });
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:10];
NSLog(@"10s --- %@", [NSThread currentThread]);
});
// ... same as before
输出为
2016-03-26 12:44:25.728 TestPlayground[28616:571502] start --- <NSThread: 0x7fb7c1604250>{number = 2, name = (null)}
2016-03-26 12:44:35.733 TestPlayground[28616:571511] 10s --- <NSThread: 0x7fb7c1422e40>{number = 3, name = (null)}
2016-03-26 12:44:35.734 TestPlayground[28616:571517] First: 5s --- <NSThread: 0x7fb7c16032d0>{number = 4, name = (null)}
2016-03-26 12:44:35.734 TestPlayground[28616:571511] Second: 5s --- <NSThread: 0x7fb7c1422e40>{number = 3, name = (null)}
2016-03-26 12:44:35.734 TestPlayground[28616:571552] Third: 5s --- <NSThread: 0x7fb7c1608950>{number = 5, name = (null)}
考虑以下输出:
00:53:38.852 asdfasdfasdf[11650:2114104] start
00:53:38.854 asdfasdfasdf[11650:2114104] main <NSThread: 0x100206110>{number = 1, name = main}
00:53:38.854 asdfasdfasdf[11650:2114126] Enter sleep block
00:53:38.854 asdfasdfasdf[11650:2114127] bare async
00:53:48.858 asdfasdfasdf[11650:2114126] Sleep block done (10 seconds).
00:53:48.859 asdfasdfasdf[11650:2114126] dispatch_after() 5 --- <NSThread: 0x10020aa00>{number = 2, name = (null)}
因此,休眠线程不会阻止异步排队块的调用(即使线程睡眠被抛出),但它会阻止 dispatch_after() 的执行。
这让我很困惑。 rdar://25373048
dispatch_queue_t queue = dispatch_queue_create("sc", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"start");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"main %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"Enter sleep block");
[NSThread sleepForTimeInterval:10];
NSLog(@"Sleep block done (10 seconds).");
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{
NSLog(@"dispatch_after() 5 --- %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"bare async");
});
});
[[NSRunLoop currentRunLoop] run];
测试代码如下:
dispatch_queue_t queue = dispatch_queue_create("sc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:10];
NSLog(@"10s --- %@", [NSThread currentThread]);
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{
NSLog(@"First: 5s --- %@", [NSThread currentThread]);
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{
NSLog(@"Second: 5s --- %@", [NSThread currentThread]);
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{
NSLog(@"Third: 5s --- %@", [NSThread currentThread]);
});
这里我创建了一个并发队列,并使用异步方式休眠一个线程。
然而,输出是:
2016-03-26 12:17:57.164 TestPlayground[28188:551287] 10s --- <NSThread: 0x7fa080511730>{number = 2, name = (null)}
2016-03-26 12:17:57.165 TestPlayground[28188:551287] First: 5s --- <NSThread: 0x7fa080511730>{number = 2, name = (null)}
2016-03-26 12:17:57.166 TestPlayground[28188:551307] Second: 5s --- <NSThread: 0x7fa080704a80>{number = 3, name = (null)}
2016-03-26 12:17:57.166 TestPlayground[28188:551301] Third: 5s --- <NSThread: 0x7fa080511530>{number = 4, name = (null)}
GCD 似乎阻塞了第一个线程 10 秒,然后开始为并发工作创建新线程。
但是如果我只是将自建队列替换成全局并发队列,不改变下面的作业
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// ... same as before
输出更合理
2016-03-26 12:23:29.496 TestPlayground[28320:558467] First: 5s --- <NSThread: 0x7ff473c08b80>{number = 4, name = (null)}
2016-03-26 12:23:29.496 TestPlayground[28320:558483] Second: 5s --- <NSThread: 0x7ff473f18c50>{number = 2, name = (null)}
2016-03-26 12:23:29.496 TestPlayground[28320:558471] Third: 5s --- <NSThread: 0x7ff473d0a7c0>{number = 3, name = (null)}
2016-03-26 12:23:34.030 TestPlayground[28320:558456] 10s --- <NSThread: 0x7ff473e218e0>{number = 5, name = (null)}
GCD 中对此类作业的调度规则是什么?为什么自建并发队列和全局队列不一样?
如果我在睡眠作业前添加新作业
dispatch_queue_t queue = dispatch_queue_create("sc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{ NSLog(@"start --- %@", [NSThread currentThread]); });
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:10];
NSLog(@"10s --- %@", [NSThread currentThread]);
});
// ... same as before
输出为
2016-03-26 12:44:25.728 TestPlayground[28616:571502] start --- <NSThread: 0x7fb7c1604250>{number = 2, name = (null)}
2016-03-26 12:44:35.733 TestPlayground[28616:571511] 10s --- <NSThread: 0x7fb7c1422e40>{number = 3, name = (null)}
2016-03-26 12:44:35.734 TestPlayground[28616:571517] First: 5s --- <NSThread: 0x7fb7c16032d0>{number = 4, name = (null)}
2016-03-26 12:44:35.734 TestPlayground[28616:571511] Second: 5s --- <NSThread: 0x7fb7c1422e40>{number = 3, name = (null)}
2016-03-26 12:44:35.734 TestPlayground[28616:571552] Third: 5s --- <NSThread: 0x7fb7c1608950>{number = 5, name = (null)}
考虑以下输出:
00:53:38.852 asdfasdfasdf[11650:2114104] start
00:53:38.854 asdfasdfasdf[11650:2114104] main <NSThread: 0x100206110>{number = 1, name = main}
00:53:38.854 asdfasdfasdf[11650:2114126] Enter sleep block
00:53:38.854 asdfasdfasdf[11650:2114127] bare async
00:53:48.858 asdfasdfasdf[11650:2114126] Sleep block done (10 seconds).
00:53:48.859 asdfasdfasdf[11650:2114126] dispatch_after() 5 --- <NSThread: 0x10020aa00>{number = 2, name = (null)}
因此,休眠线程不会阻止异步排队块的调用(即使线程睡眠被抛出),但它会阻止 dispatch_after() 的执行。
这让我很困惑。 rdar://25373048
dispatch_queue_t queue = dispatch_queue_create("sc", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"start");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"main %@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"Enter sleep block");
[NSThread sleepForTimeInterval:10];
NSLog(@"Sleep block done (10 seconds).");
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{
NSLog(@"dispatch_after() 5 --- %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"bare async");
});
});
[[NSRunLoop currentRunLoop] run];