美文网首页ios面试题
ios 中同步 异步 串行 并行

ios 中同步 异步 串行 并行

作者: 幽玄727 | 来源:发表于2021-08-19 09:56 被阅读0次

    一:定义

    同步(sync):任务一个接着一个,前一个没有执行完,后面不能执行,不开线程。

    异步(async):开启多个新线程,任务同一时间可以一起执行。异步是多线程的代名词

    最大的区别在于,同步线程要阻塞当前线程,必须要等待同步线程中的任务执行完,返回以后,才能继续执行下一任务;而异步线程则是不用等待。

    阻塞一般是指:在调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会被唤醒执行后续的操作。

    队列:装载线程任务的队形结构。(系统以先进先出的方式调度队列中的任务执行)。在GCD中有两种队列:串行队列和并发队列。

    并发队列Concurrent Dispatch Queue:线程可以同时一起进行执行。实际上是CPU在多条线程之间快速的切换。(并发功能只有在异步(dispatch_async)函数下才有效)

    串行队列Serial Dispatch Queue:线程只能依次有序的执行。

    主队列的任务一定在主线程中执行

    主线程可以执行主队列之外其他队列的任务.

    串行与并行针对的是队列,而同步与异步,针对的则是线程

    二:详解IOS串行队列与并行队列进行同步或者异步的实例

    IOS中GCD的队列分为串行队列和并行队列,任务分为同步任务和异步任务,他们的排列组合有四种情况,下面分析这四种情况的工作方式。

    同步任务,使用GCD dispatch_sync 进行派发任务
    - (void)testSync {
      dispatch_queue_t serialQueue = dispatch_queue_create("com.zyt.queue", DISPATCH_QUEUE_SERIAL);
      dispatch_queue_t concurrentQueue = dispatch_queue_create("com.zyt.queue", DISPATCH_QUEUE_CONCURRENT);
     
      NSLog(@"====serialQueue====");
      for (int i = 0; i<10; i++) {
        dispatch_sync(serialQueue, ^{
          [NSThread sleepForTimeInterval:0.3];
          NSLog(@"==>%@ sync serial XXX>%d", [NSThread currentThread], i);
        });
      }
     
      NSLog(@"====concurrentQueue====");
      for (int i = 0; i<10; i++) {
        dispatch_sync(concurrentQueue, ^{
          [NSThread sleepForTimeInterval:0.3];
          NSLog(@"==>%@ sync concurrent ====>%d", [NSThread currentThread], i*i);
        });
      }
    }
    
    //结果:
    
    2017-03-01 01:36:22.835 Demo ====serialQueue====
    2017-03-01 01:36:23.207 {number = 1, name = main} sync serial XXX>0
    2017-03-01 01:36:23.578 {number = 1, name = main} sync serial XXX>1
    2017-03-01 01:36:23.952 {number = 1, name = main} sync serial XXX>2
    2017-03-01 01:36:24.325 {number = 1, name = main} sync serial XXX>3
    2017-03-01 01:36:24.699 {number = 1, name = main} sync serial XXX>4
    2017-03-01 01:36:25.072 {number = 1, name = main} sync serial XXX>5
    2017-03-01 01:36:25.446 {number = 1, name = main} sync serial XXX>6
    2017-03-01 01:36:25.746 {number = 1, name = main} sync serial XXX>7
    2017-03-01 01:36:26.122 {number = 1, name = main} sync serial XXX>8
    2017-03-01 01:36:26.489 {number = 1, name = main} sync serial XXX>9
    2017-03-01 01:36:26.489 Demo ====concurrentQueue====
    2017-03-01 01:36:26.864 {number = 1, name = main} sync concurrent ====>0
    2017-03-01 01:36:27.236 {number = 1, name = main} sync concurrent ====>1
    2017-03-01 01:36:27.611 {number = 1, name = main} sync concurrent ====>4
    2017-03-01 01:36:27.985 {number = 1, name = main} sync concurrent ====>9
    2017-03-01 01:36:28.354 {number = 1, name = main} sync concurrent ====>16
    2017-03-01 01:36:28.726 {number = 1, name = main} sync concurrent ====>25
    2017-03-01 01:36:29.100 {number = 1, name = main} sync concurrent ====>36
    2017-03-01 01:36:29.474 {number = 1, name = main} sync concurrent ====>49
    2017-03-01 01:36:29.849 {number = 1, name = main} sync concurrent ====>64
    2017-03-01 01:36:30.223 {number = 1, name = main} sync concurrent ====>81
    
    

    testSync方法是在主线程中调用的,结果看到使用的串行队列和使用并行队列看到的结果都是发生在当前线程:主线程中,没有开启新的线程处理任务,任务的调度也是串行调度的。

    异步任务,使用GCD dispatch_async 进行派发任务
    - (void)testAsync {
      dispatch_queue_t serialQueue = dispatch_queue_create("com.zyt.queue", DISPATCH_QUEUE_SERIAL);
      dispatch_queue_t concurrentQueue = dispatch_queue_create("com.zyt.queue", DISPATCH_QUEUE_CONCURRENT);
     
      NSLog(@"====serialQueue====");
      for (int i = 0; i<10; i++) {
        dispatch_async(serialQueue, ^{
          [NSThread sleepForTimeInterval:0.3];
          NSLog(@"==>%@ async serial XXX>%d", [NSThread currentThread], i);
        });
      }
     
      NSLog(@"====concurrentQueue====");
      for (int i = 0; i<10; i++) {
        dispatch_async(concurrentQueue, ^{
          [NSThread sleepForTimeInterval:0.3];
          NSLog(@"==>%@ async concurrent ====>%d", [NSThread currentThread], i*i);
        });
      }
    }
    
    //结果:
    2017-03-01 01:45:36.125 Demo ====serialQueue====
    2017-03-01 01:45:36.125 Demo ====concurrentQueue====
    2017-03-01 01:45:36.494 {number = 3, name = (null)} async concurrent ====>0
    2017-03-01 01:45:36.494 {number = 5, name = (null)} async concurrent ====>4
    2017-03-01 01:45:36.494 {number = 4, name = (null)} async concurrent ====>1
    2017-03-01 01:45:36.494 {number = 6, name = (null)} async concurrent ====>16
    2017-03-01 01:45:36.494 {number = 8, name = (null)} async serial XXX>0
    2017-03-01 01:45:36.494 {number = 7, name = (null)} async concurrent ====>9
    2017-03-01 01:45:36.494 {number = 9, name = (null)} async concurrent ====>25
    2017-03-01 01:45:36.494 {number = 11, name = (null)} async concurrent ====>49
    2017-03-01 01:45:36.494 {number = 10, name = (null)} async concurrent ====>36
    2017-03-01 01:45:36.501 {number = 13, name = (null)} async concurrent ====>81
    2017-03-01 01:45:36.501 {number = 12, name = (null)} async concurrent ====>64
    2017-03-01 01:45:36.869 {number = 8, name = (null)} async serial XXX>1
    2017-03-01 01:45:37.244 {number = 8, name = (null)} async serial XXX>2
    2017-03-01 01:45:37.615 {number = 8, name = (null)} async serial XXX>3
    2017-03-01 01:45:37.986 {number = 8, name = (null)} async serial XXX>4
    2017-03-01 01:45:38.358 {number = 8, name = (null)} async serial XXX>5
    2017-03-01 01:45:38.730 {number = 8, name = (null)} async serial XXX>6
    2017-03-01 01:45:39.103 {number = 8, name = (null)} async serial XXX>7
    2017-03-01 01:45:39.472 {number = 8, name = (null)} async serial XXX>8
    2017-03-01 01:45:39.842 {number = 8, name = (null)} async serial XXX>9
    

    testSync方法是在主线程中调用的,结果看到使用的串行队列的异步任务会开启一个子线程执行任务,任务的调度是串行的
    使用并行队列的异步任务会开启多个子线程并行的处理任务,任务的先后顺序是不固定的,任务的调度方式是并行的

    总结

    同步任务:和使用的队列无关,不会开启子线程处理任务,会在当前的线程中串行的调度任务,即一个任务完成之后继续下一个任务,如果同步任务在主线程中调用,会阻塞主线程
    异步任务:a. 使用串行队列,会开启一个子线程串行的调度任务 b. 使用并行队列,会开启多个子线程并行的调度任务,这种情况用的是最多的

    相关文章

      网友评论

        本文标题:ios 中同步 异步 串行 并行

        本文链接:https://www.haomeiwen.com/subject/dkyobltx.html