zoukankan      html  css  js  c++  java
  • iOS-线程之GCD方式---之同步异步和串行队列并行队列之间的关系

    GCD方式是Apple官方推荐实现多线程的方式

    但在这之前必须理清楚同步,异步,串行队列,并行队列之间的概念.

    同步:即当前的执行程序块不会创建一个新的线程,只能在当前线程中执行.

    异步:会在当前的线程之外创建一个新的线程,并在新的线程中执行代码块.

    首先声明一点,队列是用来存放即将执行的线程体的.

    串行队列:串行队列中的线程满足FIFO(First In First Out),并且只有在先出的线程执行完,后续的线程才能出队列执行.(很可能造成APP的假死状态)

    并行队列:并行队列也满足FIFO,只有利用并行队列和异步的方式配合才能实现多线程同时执行(后面会讲到)

    下面的代码部分的四种情况

    1.串行队列和同步方式(不推荐使用)

     1 //1.同步方式向串行队列提交代码
     2 //前面的线程执行完成后,才会开始执行后面的线程
     3 - (void)testSyncWithSerialQueue
     4 {
     5     //串行队列
     6     dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
     7     
     8     //线程一
     9     dispatch_sync(serialQueue, ^(void){
    10         for (int i=0; i<100; i++) {
    11             NSLog(@"线程一:%d",i);
    12         }
    13     });
    14     
    15     //线程二
    16     dispatch_sync(serialQueue, ^(void){
    17         for (int i=0; i<100; i++) {
    18             NSLog(@"线程二:%d",i);
    19         }
    20     });
    21 }

    执行结果及结论:---前面的线程执行完成后,才会开始执行后面的线程

    2015-08-08 19:59:35.730 TestAsyncAndSync[3187:141197] 线程一:96

    2015-08-08 19:59:35.730 TestAsyncAndSync[3187:141197] 线程一:97

    2015-08-08 19:59:35.731 TestAsyncAndSync[3187:141197] 线程一:98

    2015-08-08 19:59:35.731 TestAsyncAndSync[3187:141197] 线程一:99

    2015-08-08 19:59:35.731 TestAsyncAndSync[3187:141197] 线程二:0

    2015-08-08 19:59:35.731 TestAsyncAndSync[3187:141197] 线程二:1

    2015-08-08 19:59:35.731 TestAsyncAndSync[3187:141197] 线程二:2

    2015-08-08 19:59:35.731 TestAsyncAndSync[3187:141197] 线程二:3

     

    2.串行队列和异步方式

     1 - (void)testAsyncWithSerialQueue
     2 {
     3     dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
     4     //异步,线程一
     5     dispatch_async(serialQueue, ^(void){
     6         for (int i=0; i<100; i++) {
     7             NSLog(@"线程1:%d",i);
     8         }
     9     });
    10     
    11     //异步:线程二
    12     dispatch_async(serialQueue, ^(void){
    13         for (int i=0; i<100; i++) {
    14             NSLog(@"线程2:%d",i);
    15         }
    16     });
    17 }

    执行结果及结论:串行队列前面的线程执行完才能执行后面的线程

    2015-08-08 20:03:28.391 TestAsyncAndSync[3225:143307] 线程1:97

    2015-08-08 20:03:28.391 TestAsyncAndSync[3225:143307] 线程1:98

    2015-08-08 20:03:28.391 TestAsyncAndSync[3225:143307] 线程1:99

    2015-08-08 20:03:28.391 TestAsyncAndSync[3225:143307] 线程2:0

    2015-08-08 20:03:28.391 TestAsyncAndSync[3225:143307] 线程2:1

    2015-08-08 20:03:28.392 TestAsyncAndSync[3225:143307] 线程2:2

     

    3.并行队列和同步方式创建线程

     1 - (void)testSyncWithConcurrentQueue
     2 {
     3     dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
     4     //线程一
     5     dispatch_sync(concurrentQueue, ^(void){
     6         for (int i=0; i<100; i++) {
     7             NSLog(@"线程一:%d",i);
     8         }
     9     });
    10     
    11     //线程一
    12     dispatch_sync(concurrentQueue, ^(void){
    13         for (int i=0; i<100; i++) {
    14             NSLog(@"线程二:%d",i);
    15         }
    16     });
    17 }

    结果和结论:先执行线程一,再执行线程二

    2015-08-08 20:06:19.111 TestAsyncAndSync[3257:144554] 线程一:97

    2015-08-08 20:06:19.111 TestAsyncAndSync[3257:144554] 线程一:98

    2015-08-08 20:06:19.111 TestAsyncAndSync[3257:144554] 线程一:99

    2015-08-08 20:06:19.112 TestAsyncAndSync[3257:144554] 线程二:0

    2015-08-08 20:06:19.112 TestAsyncAndSync[3257:144554] 线程二:1

    2015-08-08 20:06:19.112 TestAsyncAndSync[3257:144554] 线程二:2

     

    4.并行队列和异步方式

     1 - (void)testAsyncWithConcurrentQueue
     2 {
     3     dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
     4     //异步,线程一
     5     dispatch_async(concurrentQueue, ^(void){
     6         for (int i=0; i<100; i++) {
     7             NSLog(@"线程1:%d",i);
     8         }
     9     });
    10     
    11     //异步:线程二
    12     dispatch_async(concurrentQueue, ^(void){
    13         for (int i=0; i<100; i++) {
    14             NSLog(@"线程2:%d",i);
    15         }
    16     });
    17     
    18 }

    执行结果及结论:线程一和线程二同时执行

    2015-08-08 20:07:48.318 TestAsyncAndSync[3283:145696] 线程1:0

    2015-08-08 20:07:48.318 TestAsyncAndSync[3283:145693] 线程2:0

    2015-08-08 20:07:48.319 TestAsyncAndSync[3283:145693] 线程2:1

    2015-08-08 20:07:48.319 TestAsyncAndSync[3283:145693] 线程2:2

    2015-08-08 20:07:48.319 TestAsyncAndSync[3283:145693] 线程2:3

    2015-08-08 20:07:48.319 TestAsyncAndSync[3283:145696] 线程1:1

     

    再解释上述的四种情况:不得不说,线程队列是一种神奇的东西,似乎无法控制,又有迹可循...

    为什么会造成上面的四种情况呢:

    首先来说说第四种情况,异步方式创建线程并使用并行队列存放.主要是因为并行队列允许队列中的线程体出队列后,立马下一个线程体就可以出队列.而使用异步的方式,每一个出来的线程体会创建一个新的线程执行对应的代码块.所以就产生两个线程同时执行的情况.(但是也有让你感到无力的,你无法完全的控制两个线程,即使先出队列线程,也不一定先执行完,线程执行的快慢主要在于两个线程抢占系统资源获得的多少)

    第一种和第二种情况:由于串行只允许先进队列的线程,出队列后执行完才能再下一个线程出队列,所以一定是有序(根据进队列的先后)

    第三种情况:并行同步方式:虽然并行队列允许多个线程同时出队列(还是先进先出的方式),但是先出的线程不会创建新的线程,只能在当前线程中执行任务,由于当前线程只有一个,所有即使同时出队列多个线程,也只能出于等待.

  • 相关阅读:
    C# 关键字 之 virtual
    Set NOCOUNT 和 SET XACT_ABORT
    radl+ReportViewer (转)
    销售利润分析案例
    实现动态展现报表:2种开发思路
    jdk,tomcat,myecplise程序安装步骤
    BI报表工具选型的整理总结
    MyEclipse 快捷键
    oracle biee
    跨数据库
  • 原文地址:https://www.cnblogs.com/BeyondAverage0908/p/4713826.html
Copyright © 2011-2022 走看看