zoukankan      html  css  js  c++  java
  • 06-GCD基本使用和组合

    GCD


    GCD的概念(自动管理)

    • GCD有两个核心概念
      • 任务 :执行什么操作
      • 队列 :用来存放任务
    • GCD的使用步骤
      • 定制任务
        • 确定想做的事
      • 将任务添加到队列中
        • GCD会自动将队列中的任务取出,放到对应的线程中执行
        • FIFO 先进先出原则
    • 执行任务
      • 同步
        • dispath_sync(dispath_queue_t queue,^(void)block)
      • 异步
        • dispath_async(dispath_queue_t queue,^(void)block)
      • 同步和异步的区别:
        • 同步: 只能在当前线程中执行任务,不具备开启新县城的能力
        • 异步: 可以在新的线程中执行任务,具备开启新线程的能力
    //dispath_queue_t 队列
    //^(void)block 任务
    dispath_async(dispath_queue_t queue,^(void)block)
    

    同步/异步/并发/串行

    • 同步:不能开启新线程

    • 异步:可以开启新线程

    • 并发:可以开启多个子线程

    • 串行:只能在一个线程中执行(默认是串行队列)

    • 注意

      • 如果是同步函数,那么会等到函数中的任务执行完毕,才会执行后面的代码
      • 如果是异步函数,那么不用等到函数中的任务执行完毕,就会执行后面的代码

    --

    系统提供的并发队列

    // 系统内部已经给我们提供好了一个现成的并发队列
    dispath_queue_t queue = dispath_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    //异步函数调用
    dispath_async(queue,^(void)block)
    
    系统提供的并发队列参数解析:
    • 第一个参数: iOS8以前是优先级, iOS8以后是服务质量

      • iOS8以前

          • DISPATCH_QUEUE_PRIORITY_HIGH 高优先级 2
          • DISPATCH_QUEUE_PRIORITY_DEFAULT: 默认的优先级 0
          • DISPATCH_QUEUE_PRIORITY_LOW: 低优先级 -2
          • DISPATCH_QUEUE_PRIORITY_BACKGROUND:
      • iOS8以后

          • QOS_CLASS_USER_INTERACTIVE 0x21 用户交互(用户迫切想执行任务)
          • QOS_CLASS_USER_INITIATED 0x19 用户需要
          • QOS_CLASS_DEFAULT 0x15 默认
          • QOS_CLASS_UTILITY 0x11 工具(低优先级, 苹果推荐将耗时操作放到这种类型的队列中)
          • QOS_CLASS_BACKGROUND 0x09 后台
          • QOS_CLASS_UNSPECIFIED 0x00 没有设置
    • 第二个参数: 废物(写0就是default,不管在ios8以前还是以后)

      • dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    创建自定义队列,将任务加到队列中

    • 任务多的话使用dispath_async会开启新线程
    • 如果是并发,那么会开启多个线程(根据任务多少决定开启线程个数,一个线程可能处理多个任务)
    串行队列+异步函数调用
    • 会开启新的线程,但只会开启一个新的线程
    - (void)syncSerial{
     // 1.创建串行队列
        dispatch_queue_t queue = dispatch_queue_create("com.520it.ln", DISPATCH_QUEUE_SERIAL);
        //#define DISPATCH_QUEUE_SERIAL NULL
        //串行等于NULL
        /*
         能够创建新线程的原因:
         我们是使用"异步"函数调用
         只创建1个子线程的原因:
         我们的队列是串行队列
         */
        // 2.将任务添加到队列中
        dispatch_async(queue, ^{
            NSLog(@"任务1  == %@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务2  == %@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务3  == %@", [NSThread currentThread]);
        });
    }
    
    串行队列+同步函数调用
    • 不会开启新的线程
    - (void)syncSeral
    {
     // 1.创建串行队列
        dispatch_queue_t queue = dispatch_queue_create("com.520it.ln", DISPATCH_QUEUE_SERIAL);
        /*
         能够创建新线程的原因:
         我们是使用"异步"函数调用
         只创建1个子线程的原因:
         我们的队列是串行队列
         */
        // 2.将任务添加到队列中
        dispatch_sync(queue, ^{
            NSLog(@"任务1  == %@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务2  == %@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务3  == %@", [NSThread currentThread]);
        });
    }
    
    并发队列+同步函数调用
    - (void)syncConCurrent
    {
     // 1.创建串行队列
        dispatch_queue_t queue = dispatch_queue_create("com.520it.ln", DISPATCH_QUEUE_CONCURRENT);
        /*
         能够创建新线程的原因:
         我们是使用"异步"函数调用
         只创建1个子线程的原因:
         我们的队列是串行队列
         */
        // 2.将任务添加到队列中
        dispatch_sync(queue, ^{
            NSLog(@"任务1  == %@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务2  == %@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务3  == %@", [NSThread currentThread]);
        });
    }
    
    并发队列+异步函数调用
    - (void)asyncConCurrent
    {
     // 1.创建串行队列
        dispatch_queue_t queue = dispatch_queue_create("com.520it.ln", DISPATCH_QUEUE_CONCURRENT);
        /*
         能够创建新线程的原因:
         我们是使用"异步"函数调用
         只创建1个子线程的原因:
         我们的队列是串行队列
         */
        // 2.将任务添加到队列中
        dispatch_async(queue, ^{
            NSLog(@"任务1  == %@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务2  == %@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务3  == %@", [NSThread currentThread]);
        });
    }
    

    --

    主队列

    • 特点: 只要将任务添加到主队列中,那么任务一定会在主线程中执行,无论你是调用同步函数还是异步函数
    • 主队列默认是串行
    • 异步 + 主队列 :不会创建新的线程,并且任务是在主线程中执行
    • 如果是异步函数,那么不用等到函数中的任务执行完毕,就会执行后面的代码,不会产生死锁.
    - (void)asyncMain{
    dispath_queue_t queue = dispatch_get_main_queue();
    
    //即便是异步函数,在主队列中也不会创建新的线程
    dispath_async(queue,^{
    	NSLog(@"%@",[NSThread currentThread]);
    });
    }
    
    注意避免死锁
    • 导致死锁的原因(同步+主队列)
      • sync函数在主线程中执行,并且会等待block执行完毕,先调用
      • block是添加到主队列中的,也需要主线程中执行,后调用
      • 注意:如果是同步函数,那么会等到函数中的任务执行完毕,才会执行后面的代码
    - (void) viewDidLoad
    {
    //主队列默认是串行的
    	dispath_queue_t queue = dispatch_get_main_queue();
    
    	dispath_sync(queue,^{
    	NSLog(@"%@",[NSThread currentThread]);
    	});
    }
    
    • 解决办法
      • block在子线程执行
    - (void) viewDidLoad
    {
    //系统提供的并发队列
    	dispath_queue_t = queue = dispatch_get_global_queue(0,0);
    	
    	dispath_async(queue,^{
    		//获取主线程
    		dispath_queue_t queue = dispatch_get_main_queue();
    		
    		//小技巧:
    		//此时使用同步sync:NSLog(@"--------");一定会在dispatch执行完毕后执行
    		//若使用异步async:NSLog(@"--------");不一定会在dispatch执行完毕后执行
    		dispath_sync(queue,^{
    		NSLog(@"%@",[NSThread currentThread]);
    		});
    		NSLog(@"--------");
    	});
    }
    
  • 相关阅读:
    ClickHouse 详解
    SparkStreaming(二)--SparkStreaming整合Kafka
    SparkStreaming(一)--核心概念及算子
    毕设进度-3月22日
    毕设进度-3月21日
    毕设进度-3月14日
    毕设进度-3月13日
    毕设进度-3月12日
    毕设进度-3月11日
    毕设进度-3月10日
  • 原文地址:https://www.cnblogs.com/KrystalNa/p/4780324.html
Copyright © 2011-2022 走看看