zoukankan      html  css  js  c++  java
  • GCD的使用

    Dispatch Queue
    Dispatch Queue是用来执行任务的队列,是GCD中最基本的元素之一。
    Dispatch Queue分为两种:
    Serial Dispatch Queue,按添加进队列的顺序(先进先出)一个接一个的执行
    Concurrent Dispatch Queue,并发执行队列里的任务
    简而言之,Serial Dispatch Queue只使用了一个线程,Concurrent Dispatch Queue使用了多个线程(具体使用了多少个,由系统决定)。
    可以通过两种方式来获得Dispatch Queue
    //创建串行队列
    dispatch_queue_t serialQueue=dispatch_queue_create("com.xxx", DISPATCH_QUEUE_SERIAL);

    //创建并行行队列
    dispatch_queue_t concurrentQueue=dispatch_queue_create("com.xxx", DISPATCH_QUEUE_CONCURRENT);


    第一个参数是队列的名称,一般是使用倒序的全域名。虽然可以不给队列指定一个名称,但是有名称的队列可以让我们在遇到问题时更好调试;当第二个参数为nil时返回Serial Dispatch Queue,如上面那个例子,当指定为DISPATCH_QUEUE_CONCURRENT时返回Concurrent Dispatch Queue。
    第二种方式是直接获取系统提供的Dispatch Queue。
    要获取的Dispatch Queue无非就是两种类型:
    Main Dispatch Queue
    Global Dispatch Queue / Concurrent Dispatch Queue
    一般只在需要更新UI时我们才获取Main Dispatch Queue,其他情况下用Global Dispatch Queue就满足需求了:
    //主线程
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    //子线程
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_after
    dispatch_after能让我们添加进队列的任务延时执行,比如想让一个Block在10秒后执行:
    double delayInSeconds = 10.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    NSLog(@"电充好了");
    });
    NSEC_PER_SEC表示的是秒数,它还提供了NSEC_PER_MSEC表示毫秒。
    这句dispatch_after的真正含义是在10秒后把任务添加进队列中,并不是表示在10秒后执行

    dispatch_group
    //执行组 集团
    可能经常会有这样一种情况:我们现在有3个Block要执行,我们不在乎它们执行的顺序,我们只希望在这3个Block执行完之后再执行某个操作。这个时候就需要使用dispatch_group了:
    dispatch_group_t g=dispatch_group_create();
    dispatch_group_async(g, concurrentQueue, ^(void){
    NSLog(@"电充好了");
    });
    dispatch_group_notify(g, concurrentQueue, ^(void){
    NSLog(@"电充好了1");
    });
    输出的顺序与添加进队列的顺序无关,因为队列是Concurrent Dispatch Queue,但“completed”的输出一定是在最后的:电充好了1
    除了使用dispatch_group_notify函数可以得到最后执行完的通知外,还可以使用
    需要注意的是,dispatch_group_wait实际上会使当前的线程处于等待的状态,也就是说如果是在主线程执行dispatch_group_wait,在上面的Block执行完之前,主线程会处于卡死的状态。可以注意到dispatch_group_wait的第二个参数是指定超时的时间,如果指定为DISPATCH_TIME_FOREVER(如上面这个例子)则表示会永久等待,直到上面的Block全部执行完,除此之外,还可以指定为具体的等待时间,根据dispatch_group_wait的返回值来判断是上面block执行完了还是等待超时了。
    dispatch_group_t g=dispatch_group_create();
    dispatch_group_async(g, concurrentQueue, ^(void){
    NSLog(@"电充好了");
    });
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
    NSLog(@"电充好了1");

    dispatch_barrier_async
    dispatch_barrier_async就如同它的名字一样,在队列执行的任务中增加“栅栏”,在增加“栅栏”之前已经开始执行的block将会继续执行,当dispatch_barrier_async开始执行的时候其他的block处于等待状态,dispatch_barrier_async的任务执行完后,其后的block才会执行

    - (void)writeFilek{
    [[NSUserDefaults standardUserDefaults]setInteger:7 forKey:@"integer"];
    }
    - (void)readFile{
    NSLog(@"%i",[[NSUserDefaults standardUserDefaults]integerForKey:@"integer"]);
    }

    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(globalQueue, ^(void){
    [self readFile];
    });
    dispatch_async(globalQueue, ^(void){
    [self readFile];
    });
    dispatch_async(globalQueue, ^(void){
    [self readFile];
    });
    dispatch_barrier_async(globalQueue, ^(void){
    [self writeFilek];
    [self readFile];
    });
    dispatch_async(globalQueue, ^(void){
    [self readFile];
    });
    dispatch_async(globalQueue, ^(void){
    [self readFile];
    });
    dispatch_async(globalQueue, ^(void){
    [self readFile];
    });

    由于这个队列是一个Concurrent Dispatch Queue,能同时并发多少线程是由系统决定的,如果添加dispatch_barrier_async的时候,其他的block(包括上面4个block)还没有开始执行,那么会先执行dispatch_barrier_async里的任务,其他block全部处于等待状态。如果添加dispatch_barrier_async的时候,已经有block在执行了,那么dispatch_barrier_async会等这些block执行完后再执行。

    dispatch_apply
    dispatch_apply会将一个指定的block执行指定的次数。如果要对某个数组中的所有元素执行同样的block的时候,这个函数就显得很有用了,用法很简单,指定执行的次数以及Dispatch Queue,在block回调中会带一个索引,然后就可以根据这个索引来判断当前是对哪个元素进行操作:
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_apply(10, globalQueue, ^(size_t tem){
    NSLog(@"%lu",tem);
    });
    NSLog(@"completed");
    由于是Concurrent Dispatch Queue,不能保证哪个索引的元素是先执行的,但是“completed”一定是在最后打印,因为dispatch_apply函数是同步的,执行过程中会使线程在此处等待,所以一般的,我们应该在一个异步线程里使用dispatch_apply函数:

    dispatch_suspend / dispatch_resume
    某些情况下,我们可能会想让Dispatch Queue暂时停止一下,然后在某个时刻恢复处理,这时就可以使用dispatch_suspend以及dispatch_resume函数:
    //暂停
    dispatch_suspend(globalQueue)
    //恢复
    dispatch_resume(globalQueue)
    暂停时,如果已经有block正在执行,那么不会对该block的执行产生影响。dispatch_suspend只会对还未开始执行的block产生影响。

  • 相关阅读:
    struts2基础---->自定义拦截器
    struts2基础---->第一个Struts2程序
    Vue基础---->vue-router的使用(一)
    java框架---->zxing框架的使用
    java基础---->java输入输出流
    java基础----->TCP和UDP套接字编程
    JS基础---->js中ajax的使用
    tomcat源码---->request的请求参数分析
    Android Http请求方法汇总
    Android如何通过shareduserid获取系统权限
  • 原文地址:https://www.cnblogs.com/kkkblog/p/4209042.html
Copyright © 2011-2022 走看看