第一部分:线程与队列
线程是代码执行的路径,队列则是用于保存以及管理任务的,线程负责去队列中取任务进行执行。
例如:在主线程调用如下代码
- dispatch_sync(queue, ^{
- task()
- });
可以在task函数中log日志查看
- -(void)task
- {
- NSLog(@"1. 当前线程是: %@, 当前队列是: %@ 。",[NSThread currentThread],dispatch_get_current_queue());
- }
如果将代码改成如下:
- dispatch_async(queue, ^{
- task()
- });
则task函数同样提交到queue队列,但系统会创建辅助线程从queue中取出任务进行执行。
以上粗浅解释了IOS中的线程与队列
第二部分:GCD获取当前队列的方法以及它为何在ios6中被丢弃
- void func(dispatch_queue_t queue, dispatch_block_t block)
- {
- if (dispatch_get_current_queue() == queue) {
- block();
- }else{
- dispatch_sync(queue, block);
- }
- }
- - (void)deadLockFunc
- {
- dispatch_queue_t queueA = dispatch_queue_create("com.yiyaaixuexi.queueA", NULL);
- dispatch_queue_t queueB = dispatch_queue_create("com.yiyaaixuexi.queueB", NULL);
- dispatch_sync(queueA, ^{
- dispatch_sync(queueB, ^{
- dispatch_block_t block = ^{
-
- };
- func(queueA, block);
- });
- });
- }
dispatch_sync将会导致queueA依赖queueB,然而func函数的写法导致queueB也依赖queueA,导致死锁。
那么应该如何保证GCD方法可重入呢?
- dispatch_queue_set_specific 标记队列
dispatch_get_specific
就是在当前
队列
中取出标识
- if (dispatch_get_specific(queueKey1)) {
-
- }else{
-
- }
再看如下代码可以让你更清晰的理解线程和队列以及
dispatch_get_specific是如何取代dispatch_get_current_queue的
-
- #import
-
- int main(int argc, const charchar * argv[]) {
- @autoreleasepool {
- static voidvoid *queueKey1 = "queueKey1";
-
- dispatch_queue_t queue1 = dispatch_queue_create(queueKey1, DISPATCH_QUEUE_SERIAL);
- dispatch_queue_set_specific(queue1, queueKey1, &queueKey1, NULL);
-
- NSLog(@"1. 当前线程是: %@, 当前队列是: %@ 。",[NSThread currentThread],dispatch_get_current_queue());
-
- if (dispatch_get_specific(queueKey1)) {
-
- NSLog(@"2. 当前线程是: %@, 当前队列是: %@ 。",[NSThread currentThread],dispatch_get_current_queue());
- [NSThread sleepForTimeInterval:1];
- }else{
- NSLog(@"3. 当前线程是: %@, 当前队列是: %@ 。",[NSThread currentThread],dispatch_get_current_queue());
- [NSThread sleepForTimeInterval:1];
- }
-
- dispatch_sync(queue1, ^{
- NSLog(@"4. 当前线程是: %@, 当前队列是: %@ 。",[NSThread currentThread],dispatch_get_current_queue());
- [NSThread sleepForTimeInterval:1];
-
- if (dispatch_get_specific(queueKey1)) {
-
- NSLog(@"5. 当前线程是: %@, 当前队列是: %@ 。",[NSThread currentThread],dispatch_get_current_queue());
- [NSThread sleepForTimeInterval:1];
- }else{
- NSLog(@"6. 当前线程是: %@, 当前队列是: %@ 。",[NSThread currentThread],dispatch_get_current_queue());
- [NSThread sleepForTimeInterval:1];
- }
- });
- dispatch_async(queue1, ^{
- NSLog(@"7. t当前线程是: %@, 当前队列是: %@ 。",[NSThread currentThread],dispatch_get_current_queue());
- [NSThread sleepForTimeInterval:1];
- });
-
- [NSThread sleepForTimeInterval:5];
- }
- return 0;
- }
task函数这个任务将会提交到队列queue上,主线程负责去执行这个任务。
dispatch_get_current_queue这个方法可以很方便的获取到当前线程,可为什么要丢弃这个函数呢?请看一下代码
为了防止类似的误用,苹果在iOS6废弃了dispatch_get_current_queue()方法。强大的dispatch_get_current_queue()也只能当作一个调试工具了。
dispatch_queue_set_specific就是向指定队列里面设置一个标识 如:
dispatch_queue_set_specific(queue1, queueKey1, &queueKey1,NULL);
就是向queue1对了中设置一个queueKey1标识。
输出结果:
2016-02-19 14:31:23.390 gcd[96865:820267] 1.当前线程是: {number = 1, name = main},当前队列是: 。
2016-02-19 14:31:23.391 gcd[96865:820267] 3.当前线程是: {number = 1, name = main},当前队列是: 。
2016-02-19 14:31:24.396 gcd[96865:820267] 4.当前线程是: {number = 1, name = main},当前队列是: 。
2016-02-19 14:31:25.400 gcd[96865:820267] 5.当前线程是: {number = 1, name = main},当前队列是: 。
2016-02-19 14:31:26.402 gcd[96865:820367] 7. t当前线程是: {number = 2, name = (null)},当前队列是: 。
Program ended with exit code: 0