欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

iOS多线程:GCD详解

程序员文章站 2022-04-08 22:49:33
...

参考链接:

iOS 多线程:『GCD』详尽总结

1.对参考链接中4.5.2的补充

1.1 同步执行dispatch_sync,必须上一个执行完再执行下一个,不管这两个任务所属队列和所在线程是否相同

从下面的测试结果可以看出:同步执行任务,任务会按添加代码的先后顺序执行,写在前面的任务先执行,写在后面的任务后执行. 如“12—%@”虽然是在子线程里执行的,但是一定要等到主线程中的“1—%@”,“2—%@”执行完后再执行


- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSLog(@"调用前---%@",[NSThread currentThread]);  // 打印当前线程
     
    [NSThread detachNewThreadSelector:@selector(syncSerial) toTarget:self withObject:nil];
    
     [NSThread sleepForTimeInterval:1];
    NSLog(@"调用后---%@",[NSThread currentThread]);  // 打印当前线程
     [NSThread sleepForTimeInterval:8];
   NSLog(@"调用后1---%@",[NSThread currentThread]);
    // Do any additional setup after loading the view.
}

- (void)syncSerial {
    NSLog(@"syncSerial---begin---%@",[NSThread currentThread]);  // 打印当前线程
    
    
   dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_queue_t queue1 = dispatch_queue_create("net.bujige.testQueu", DISPATCH_QUEUE_SERIAL);
     dispatch_queue_t queue2 = dispatch_queue_create("net.bujige.testQue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(queue1, ^{
            // 追加任务 1
            [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
            NSLog(@"11---%@",[NSThread currentThread]);      // 打印当前线程
        });
       
      
        NSLog(@"queue1后---%@",[NSThread currentThread]);  // 打印当前线程
    
    dispatch_sync(queue, ^{
        // 追加任务 1
        [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
        NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
   
    
    dispatch_sync(queue, ^{
        // 追加任务 2
        [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
        NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
    
    dispatch_sync(queue1, ^{
        // 追加任务 2
        [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
        NSLog(@"12---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
    
    dispatch_sync(queue2, ^{
        // 追加任务 2
        [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
        NSLog(@"222---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
     NSLog(@"queue2后---%@",[NSThread currentThread]);
    
    dispatch_sync(queue, ^{
        // 追加任务 3
        [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
        NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
  
     NSLog(@"syncSerial---end---%@",[NSThread currentThread]);  // 打印当前线程
}

打印结果:

2020-04-23 16:37:32.310662+0800 oc-interview[2995:87379] 调用前---<NSThread: 0x6000028e5d80>{number = 1, name = main}
2020-04-23 16:37:32.311043+0800 oc-interview[2995:87488] syncSerial---begin---<NSThread: 0x6000028bba80>{number = 6, name = (null)}
2020-04-23 16:37:33.312025+0800 oc-interview[2995:87379] 调用后---<NSThread: 0x6000028e5d80>{number = 1, name = main}
2020-04-23 16:37:33.312097+0800 oc-interview[2995:87488] 11---<NSThread: 0x6000028bba80>{number = 6, name = (null)}
2020-04-23 16:37:33.312446+0800 oc-interview[2995:87488] queue1后---<NSThread: 0x6000028bba80>{number = 6, name = (null)}
2020-04-23 16:37:37.313452+0800 oc-interview[2995:87379] 调用后1---<NSThread: 0x6000028e5d80>{number = 1, name = main}
2020-04-23 16:37:38.331959+0800 oc-interview[2995:87379] 1---<NSThread: 0x6000028e5d80>{number = 1, name = main}
2020-04-23 16:37:39.345965+0800 oc-interview[2995:87379] 2---<NSThread: 0x6000028e5d80>{number = 1, name = main}
2020-04-23 16:37:40.349866+0800 oc-interview[2995:87488] 12---<NSThread: 0x6000028bba80>{number = 6, name = (null)}
2020-04-23 16:37:41.354956+0800 oc-interview[2995:87488] 222---<NSThread: 0x6000028bba80>{number = 6, name = (null)}
2020-04-23 16:37:41.355392+0800 oc-interview[2995:87488] queue2后---<NSThread: 0x6000028bba80>{number = 6, name = (null)}
2020-04-23 16:37:42.356360+0800 oc-interview[2995:87379] 3---<NSThread: 0x6000028e5d80>{number = 1, name = main}
2020-04-23 16:37:42.356839+0800 oc-interview[2995:87488] syncSerial---end---<NSThread: 0x6000028bba80>{number = 6, name = (null)}

1.2 异步执行任务

1.2.1 后面的任务不需要等它,但它还是需要等前面的执行完

只把1.1代码中的“12—”前的dispatch_sync改为 dispatch_async后得到的打印结果,"12—"不会阻碍“222—”的运行,它新开了线程
iOS多线程:GCD详解

1.2.2 如下图主队列中的3还是要等到1,2执行完了它才执行。1,2,3

下图在1.1代码的基础上,把三个红圈的地方改成了异步执行后的运行结果

iOS多线程:GCD详解

2.串行队列异步执行,会新开一条线程。并行队列异步执行会新开多条线程(如下演示)

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSLog(@"调用前---%@",[NSThread currentThread]);  // 打印当前线程
     
    [NSThread detachNewThreadSelector:@selector(syncSerial) toTarget:self withObject:nil];
    
     [NSThread sleepForTimeInterval:1];
    NSLog(@"调用后---%@",[NSThread currentThread]);  // 打印当前线程
     [NSThread sleepForTimeInterval:8];
   NSLog(@"调用后1---%@",[NSThread currentThread]);
    // Do any additional setup after loading the view.
}

- (void)syncSerial {
    NSLog(@"syncSerial---begin---%@",[NSThread currentThread]);  // 打印当前线程
    
    
   dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_queue_t queue1 = dispatch_queue_create("net.bujige.testQueu", DISPATCH_QUEUE_SERIAL);
     dispatch_queue_t queue2 = dispatch_queue_create("net.bujige.testQue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue1, ^{
            // 追加任务 1
            [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
            NSLog(@"11---%@",[NSThread currentThread]);      // 打印当前线程
        });
       
      
        NSLog(@"queue1后---%@",[NSThread currentThread]);  // 打印当前线程
    
    dispatch_async(queue1, ^{
        // 追加任务 1
        [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
        NSLog(@"12---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
   
    
    dispatch_async(queue1, ^{
        // 追加任务 2
        [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
        NSLog(@"13---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
    
    dispatch_async(queue2, ^{
        // 追加任务 2
        [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
        NSLog(@"221---%@",[NSThread currentThread]);      // 打印当前线程
    });


    dispatch_async(queue2, ^{
        // 追加任务 2
        [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
        NSLog(@"222---%@",[NSThread currentThread]);      // 打印当前线程
    });

     NSLog(@"queue2后---%@",[NSThread currentThread]);
//
//    dispatch_sync(queue, ^{
//        // 追加任务 3
//        [NSThread sleepForTimeInterval:1];              // 模拟耗时操作
//        NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
//    });
    
  
     NSLog(@"syncSerial---end---%@",[NSThread currentThread]);  // 打印当前线程
}
2020-04-23 18:19:18.891868+0800 oc-interview[4000:124178] 调用前---<NSThread: 0x600000462d00>{number = 1, name = main}
2020-04-23 18:19:18.892303+0800 oc-interview[4000:124286] syncSerial---begin---<NSThread: 0x600000401900>{number = 7, name = (null)}
2020-04-23 18:19:18.892851+0800 oc-interview[4000:124286] queue1后---<NSThread: 0x600000401900>{number = 7, name = (null)}
2020-04-23 18:19:18.893222+0800 oc-interview[4000:124286] queue2后---<NSThread: 0x600000401900>{number = 7, name = (null)}
2020-04-23 18:19:18.893576+0800 oc-interview[4000:124286] syncSerial---end---<NSThread: 0x600000401900>{number = 7, name = (null)}
2020-04-23 18:19:19.892995+0800 oc-interview[4000:124178] 调用后---<NSThread: 0x600000462d00>{number = 1, name = main}
2020-04-23 18:19:19.897289+0800 oc-interview[4000:124277] 11---<NSThread: 0x60000043bf80>{number = 5, name = (null)}
2020-04-23 18:19:19.897293+0800 oc-interview[4000:124276] 221---<NSThread: 0x60000043d7c0>{number = 6, name = (null)}
2020-04-23 18:19:19.897298+0800 oc-interview[4000:124279] 222---<NSThread: 0x600000401840>{number = 8, name = (null)}
2020-04-23 18:19:20.901891+0800 oc-interview[4000:124277] 12---<NSThread: 0x60000043bf80>{number = 5, name = (null)}
2020-04-23 18:19:21.906531+0800 oc-interview[4000:124277] 13---<NSThread: 0x60000043bf80>{number = 5, name = (null)}
2020-04-23 18:19:27.894360+0800 oc-interview[4000:124178] 调用后1---<NSThread: 0x600000462d00>{number = 1, name = main}
相关标签: ios 面试