zoukankan      html  css  js  c++  java
  • iOS 多线程的简单理解(1) 方式 :同步 异步

    最近遇到特别糟糕的面试,过程中提到多次对多线程的处理问题,并没有很好的给予答复和解决,所以在这里做个简单的备案:

    期望能更加了解和熟练使用 多线程技术:

    下面都是自己的总结,如果存在不对的,或者不足,请给予指正……

    1. 多线程基本概念:方式 -> 同步 + 异步

    1.1 同步 :  队列任务 在当前线程,按照添加先后顺序执行,不开辟新的线程;

    1.1.1   同步方法 1

    - (void)syncOne{
      
        NSLog(@"**************同步1 start ***************");
        NSLog(@"同步1 start  %@",[NSThread currentThread]);
    
        dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
        // 同步执行
        dispatch_sync(queue, ^{
            for (int i = 0; i < 3; i++) {
                NSLog(@"同步1   %@",[NSThread currentThread]);
            }
        });
        NSLog(@"同步1 end  %@",[NSThread currentThread]);
        NSLog(@"**************同步1 end ***************");
    }
    

     打印结果:::::

    2017-12-19 16:56:06.537696+0800 DeadThread[6767:1309336] **************同步1 start ***************
    2017-12-19 16:56:06.537841+0800 DeadThread[6767:1309336] 同步1 start  <NSThread: 0x6040000789c0>{number = 1, name = main}
    2017-12-19 16:56:06.537969+0800 DeadThread[6767:1309336] 同步1   <NSThread: 0x6040000789c0>{number = 1, name = main}
    2017-12-19 16:56:06.538046+0800 DeadThread[6767:1309336] 同步1   <NSThread: 0x6040000789c0>{number = 1, name = main}
    2017-12-19 16:56:06.538222+0800 DeadThread[6767:1309336] 同步1   <NSThread: 0x6040000789c0>{number = 1, name = main}
    2017-12-19 16:56:06.538307+0800 DeadThread[6767:1309336] 同步1 end  <NSThread: 0x6040000789c0>{number = 1, name = main}
    2017-12-19 16:56:06.538404+0800 DeadThread[6767:1309336] **************同步1 end ***************
    

    得到的结果::

    1.创建了同步队列:dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);

    1.线程在主线程执行

    2.线程顺序执行的

    1.1.2 同步方法 2

    - (void)syncTwo{
        
        NSLog(@"**************同步2 start ***************");
        NSLog(@"同步2 start  %@",[NSThread currentThread]);
    
        dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
        // 同步执行
        dispatch_async(dispatch_get_global_queue(0, 0), ^{//新开一个子线程
            
            dispatch_sync(queue, ^{
                for (int i = 0; i < 3; i++) {
                    NSLog(@"同步2   %@",[NSThread currentThread]);
                }
            });
       
        });
        
        NSLog(@"同步2 end  %@",[NSThread currentThread]);
        NSLog(@"**************同步2 end ***************");
    }
    

     打印结果::::

    2017-12-20 10:08:49.982236+0800 DeadThread[8035:1857644] **************同步2 start ***************
    2017-12-20 10:08:49.982373+0800 DeadThread[8035:1857644] 同步2 start  <NSThread: 0x604000075480>{number = 1, name = main}
    2017-12-20 10:08:49.982478+0800 DeadThread[8035:1857644] 同步2 end  <NSThread: 0x604000075480>{number = 1, name = main}
    2017-12-20 10:08:49.982512+0800 DeadThread[8035:1858341] 同步2   <NSThread: 0x60400026aa40>{number = 3, name = (null)}
    2017-12-20 10:08:49.982563+0800 DeadThread[8035:1857644] **************同步2 end ***************
    2017-12-20 10:08:49.982584+0800 DeadThread[8035:1858341] 同步2   <NSThread: 0x60400026aa40>{number = 3, name = (null)}
    2017-12-20 10:08:49.982817+0800 DeadThread[8035:1858341] 同步2   <NSThread: 0x60400026aa40>{number = 3, name = (null)}
    

     得到的结果:::::

     1.线程在新开的线程执行;

     2.线程内同步代码 运行是顺序进行的

    1.1.3 同步死锁

      解说一个经典的死锁代码:

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        NSLog(@"开始启动");// 1
        
        dispatch_sync(dispatch_get_main_queue(), ^{ //2
            
            NSLog(@"同步任务"); // 3 
        });
     
        NSLog(@"启动结束"); //4
    }
    

     运行结果::::

    2017-12-20 10:53:10.147278+0800 DeadThread[8403:2037075] 开始启动
    (lldb) 
    

     解说原因::::

     前提::1. viewDidLoad 任务是在主线程执行的  2. dispatch_sync(dispatch_get_main_queue(),^{ }); 在主线程 添加了新的任务

     1.项目整体代码是 顺序运行的;

     2.当代码 运行到 标记 1 时, 没有发生问题,log 正常启动,打印输出;

     3.当代码 运行到 标记 2 时,添加了新的同步任务,且在同一个队列中(如图)

     图示::

     同步任务,view did load 任务 先添加的,所以先被执行,

     运行到  标记 2 时,添加新的同步任务,此时 需要执行 这个同步任务,但此时  view did load 任务 还没有执行完毕;

     造成的结果:

      同步任务 需要等待 view did load 任务执行完毕;

      view did load 任务 需要同步任务执行 完毕;

     对不起,哥们,到了这里,程序死定了,呜呜……

    1.2 异步 :具备开启新线程的能理,执行时,不影响主线程的运行

    1.2.1  异步方法1

    - (void)asyncOne{
        
        NSLog(@"**************异步1 start ***************");
        NSLog(@"异步1 start  %@",[NSThread currentThread]);
        
        dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
        // 异步执行
        dispatch_async(queue, ^{
            for (int i = 0; i < 3; i++) {
                NSLog(@"异步1   %@",[NSThread currentThread]);
            }
        });
        NSLog(@"异步1 end  %@",[NSThread currentThread]);
        NSLog(@"**************异步1 end ***************");
    }
    

     执行结果::::

    2017-12-20 12:58:01.304660+0800 DeadThread[8552:2189332] **************异步1 start ***************
    2017-12-20 12:58:01.304867+0800 DeadThread[8552:2189332] 异步1 start  <NSThread: 0x600000078940>{number = 1, name = main}
    2017-12-20 12:58:01.304959+0800 DeadThread[8552:2189332] 异步1 end  <NSThread: 0x600000078940>{number = 1, name = main}
    2017-12-20 12:58:01.304993+0800 DeadThread[8552:2189855] 异步1   <NSThread: 0x600000272140>{number = 3, name = (null)}
    2017-12-20 12:58:01.305164+0800 DeadThread[8552:2189332] **************异步1 end ***************
    2017-12-20 12:58:01.305184+0800 DeadThread[8552:2189855] 异步1   <NSThread: 0x600000272140>{number = 3, name = (null)}
    2017-12-20 12:58:01.305255+0800 DeadThread[8552:2189855] 异步1   <NSThread: 0x600000272140>{number = 3, name = (null)}
    

     得到的结果:::

    1.不影响主线程的执行;

    2.新任务的代码,在新的线程执行;

    1.2.2 异步方法2

    - (void)asyncTwo{
        
        NSLog(@"**************异步2 start ***************");
        NSLog(@"异步2 start  %@",[NSThread currentThread]);
        
        dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
        // 异步执行
        dispatch_async(queue, ^{
            for (int i = 0; i < 3; i++) {
                NSLog(@"异步2   %@",[NSThread currentThread]);
            }
        });
        NSLog(@"异步2 end  %@",[NSThread currentThread]);
        NSLog(@"**************异步2 end ***************");
    }
    

     执行结果:::

    2017-12-20 13:16:36.866651+0800 DeadThread[8737:2276498] **************异步2 start ***************
    2017-12-20 13:16:36.866783+0800 DeadThread[8737:2276498] 异步2 start  <NSThread: 0x600000076540>{number = 1, name = main}
    2017-12-20 13:16:36.866890+0800 DeadThread[8737:2276498] 异步2 end  <NSThread: 0x600000076540>{number = 1, name = main}
    2017-12-20 13:16:36.866891+0800 DeadThread[8737:2276887] 异步2   <NSThread: 0x608000079800>{number = 3, name = (null)}
    2017-12-20 13:16:36.866960+0800 DeadThread[8737:2276498] **************异步2 end ***************
    2017-12-20 13:16:36.866980+0800 DeadThread[8737:2276887] 异步2   <NSThread: 0x608000079800>{number = 3, name = (null)}
    2017-12-20 13:16:36.867038+0800 DeadThread[8737:2276887] 异步2   <NSThread: 0x608000079800>{number = 3, name = (null)}
    

     得到结果:::

    1.不影响主线程的执行;

    2.新任务的代码,在新的线程执行;

  • 相关阅读:
    nginx配置二级目录,反向代理不同ip+端口
    一次实验环境中的数据库空间整理经历
    NFine中权限判断出错的问题
    Centos7 硬盘分区
    12个必备的JavaScript装逼技巧
    判断五大浏览器类型
    npm 常用命令及版本号浅析
    js 判断IE浏览器
    娱乐冷门小知识
    vue baidu Map 百度路书去掉动画
  • 原文地址:https://www.cnblogs.com/Bob-blogs/p/8073247.html
Copyright © 2011-2022 走看看