GCD

作者: End_枫 | 来源:发表于2017-04-28 13:00 被阅读7次

GCD

任务调度,由系统维护线程池,分配执行线程,简单高效,队列只负责任务的调度,执行在线程中

基本知识点

队列的特点:FIFO.(不管是串行的还是并发的,任务是执行顺序都是按照FIFO规则)

串行队列:任务按照顺序被调度,前一个任务不执行完毕,队列不会调度

并发队列:只要有空闲的线程,队列就会调度当前任务。

主队列:专门用来在主线程调度任务的队列

全局队列:系统提供的并发队列

同步执行:不会开启新的线程,任务按顺序执行

异步执行:会开启新的线程,任务可以并发的执行

并行:多个任务同时执行

并发:多个任务“同时”执行

根据队列的类型和执行方式,划分以下组合 (同步任务):

  1. 串行队列同步执行:依次执行。
  2. 串行队列异步执行:串行队列的特点,前一个任务不执行完毕,队列不会调度新的任务,依次执行。
  3. 并行队列同步执行:同步执行不会开启新的线程,依次执行。
  4. 并行队列异步执行:并发执行

常见方法

dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT/DISPATCH_QUEUE_SERIAL)
dispatch_sync(queue, ^{})
dispatch_async(queue, ^{})
dispatch_get_main_queue()
dispatch_get_global_queue(0, 0);
dispatch_once()

dispatch_barrier_async:用于等待前面的任务执行完毕后自己才执行,而它后面的任务需等待它完成之后才执行。

dispatch_queue_t queue = dispatch_queue_create("Database_Queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"reading data1");
    });
    dispatch_async(queue, ^{
        NSLog(@"reading data2");
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"writing data1");
        [NSThread sleepForTimeInterval:1];

    });
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"reading data3");
    });

dispatch_queue_set_specific:为队列设置唯一的标志,可用于检查当前之在的queue,避免死锁
dispatch_get_specific:获取队列标志

dispatch_apply:在指定的dispatch queue中运行block任务n次,如果队列是并发队列,则会并发执行block任务,同步调用,block任务执行n次后才返回。

dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_apply(5, queue, ^(size_t i) {
    NSLog(@"do a job %zu times",i+1);
});

dispatch_block_t:

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block = dispatch_block_create_with_qos_class(0, QOS_CLASS_USER_INITIATED, -1, ^{
        NSLog(@"do something with QoS");
    });
dispatch_async(queue, block);

dispatch_block_wait:等待前面的任务执行完毕

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block = dispatch_block_create(0, ^{
    NSLog(@"before sleep");
    [NSThread sleepForTimeInterval:1];
    NSLog(@"after sleep");
});
dispatch_async(queue, block);
//等待前面的任务执行完毕
dispatch_block_wait(block, DISPATCH_TIME_FOREVER);
NSLog(@"coutinue");

dispatch_block_notify:当观察的某个block执行结束之后立刻通知提交另一特定的block到指定的queue中执行

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
  dispatch_block_t previousBlock = dispatch_block_create(0, ^{
      NSLog(@"previousBlock begin");
      [NSThread sleepForTimeInterval:1];
      NSLog(@"previousBlock done");
  });
  dispatch_async(queue, previousBlock);
  dispatch_block_t notifyBlock = dispatch_block_create(0, ^{
      NSLog(@"notifyBlock");
  });
  //当previousBlock执行完毕后,提交notifyBlock到global queue中执行
  dispatch_block_notify(previousBlock, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), notifyBlock);

dispatch_block_cancel(iOS 8):取消提交到队列中未被调度执行的任务

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block1 = dispatch_block_create(0, ^{
    NSLog(@"block1 begin");
    [NSThread sleepForTimeInterval:1];
    NSLog(@"block1 done");
});
dispatch_block_t block2 = dispatch_block_create(0, ^{
    NSLog(@"block2 ");
});
dispatch_async(queue, block1);
dispatch_async(queue, block2);
dispatch_block_cancel(block2);

dispatch_group_wait:同步地等待group中所有的block执行完毕后才继续执行,会阻塞当前线程

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
//将任务异步地添加到group中去执行
dispatch_group_async(group,queue,^{ NSLog(@"block1"); });
dispatch_group_async(group,queue,^{ NSLog(@"block2"); });
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
NSLog(@"go on");

只有block1跟block2执行完毕后才会执行dispatch_group_wait后面的内容。

dispatch_group_notify:dispatch_group_wait类似,异步的,不会阻塞该线程

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,queue,^{ NSLog(@"block1"); });
dispatch_group_async(group,queue,^{ NSLog(@"block2"); });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
  NSLog(@"done");
});
NSLog(@"go on”);

dispatch_group_enter:对于提交到group中的任务是一个异步任务时,则需要手动处理进入/退出 group的时机
dispatch_group_leave: 成对出现

dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
    dispatch_group_leave(group);
});

dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
    dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{});

Dispatch Semaphore:信号量

//创建一个信号量,初始值为0
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"do some job");
    sleep(1);
    NSLog(@"increase the semaphore");
    dispatch_semaphore_signal(sema); //信号值加1
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);//等待直到信号值大于等1(信号值减1)

dispatch timer:通常配合dispatch_after使用,完成一些延时的任务:

//延迟5秒后调度
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC));
dispatch_after(time, dispatch_get_main_queue(), ^{
    NSLog(@"do job afer 5 seconds");
});

dispatch_source:监听系统底层对象(文件描述符、Mach端口、信号量等),当这些对象有事件产生时会自动把事件的处理block函数提交到dispatch队列中执行
DISPATCH_SOURCE_TYPE_DATA_ADD 变量增加
DISPATCH_SOURCE_TYPE_DATA_OR 变量ORDISPATCH_SOURCE_TYPE_MACH_SEND Mach端口发送
DISPATCH_SOURCE_TYPE_MACH_RECV Mach端口接收
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE 内存压力情况变化
DISPATCH_SOURCE_TYPE_PROC 与进程相关的事件
DISPATCH_SOURCE_TYPE_READ 可读取文件映像
DISPATCH_SOURCE_TYPE_SIGNAL 接收信号
DISPATCH_SOURCE_TYPE_TIMER 定时器事件
DISPATCH_SOURCE_TYPE_VNODE 文件系统变更
DISPATCH_SOURCE_TYPE_WRITE 可写入文件映像

@property (nonatomic)dispatch_source_t timerSource;

dispatch_queue_t queue = dispatch_queue_create("myqueue", NULL);

_timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
uint64_t interval = 2 * NSEC_PER_SEC;
dispatch_source_set_timer(_timerSource,DISPATCH_TIME_NOW, interval , 0);

//设置事件的处理handler
dispatch_source_set_event_handler(_timerSource, ^{
    NSLog(@"receive time event");
    //if (done) 
    //   dispatch_source_cancel(_timerSource); 
});

dispatch_resume(_timerSource);

相关文章

  • 多线程之GCD

    GCD介绍 1、GCD简介 2、GCD任务和队列 3、GCD 的基本使用 4、GCD 线程间的通信 5、GCD 的...

  • 扩展GCD(求逆元,解同余方程等等)

    首先要知道gcd函数的基本性质:gcd(a,b)=gcd(b,a)=gcd(|a|,|b|)=gcd(b,a%b)...

  • iOS - GCD

    目录 GCD简介 GCD核心概念 GCD队列的使用 GCD的常见面试题 GCD简介 Grand Central D...

  • iOS-多线程:GCD

    GCD 简介 GCD 任务和队列 GCD 的使用步骤 GCD 的基本使用(6种不同组合区别) GCD 线程间的通信...

  • 浅析GCD

    GCD目录: 1. GCD简介 为什么要用GCD呢? GCD可用于多核的并行运算GCD会自动利用更多的CPU内核(...

  • 7.3 多线程-GCD

    多线程-GCD 多线程-GCD-串行并行 多线程-GCD.png GCD-线程的通讯、延时操作、定时器 GCD-线...

  • iOS 多线程--GCD

    一、GCD基本介绍 1.GCD简介 GCD是Grand Central Dispatch的缩写,GCD是苹果推出的...

  • 自用算法模板(JAVA版)

    一、数论 1)GCD GCD(求最大公约数) QGCD(快速GCD) extGCD(拓展GCD,解决ax + by...

  • GCD介绍

    一、GCD简单介绍 什么是GCD GCD优势 任务和队列 GCD有2个核心概念 GCD的使用就2个步骤 将任务添加...

  • 7.多线程基础(七)GCD加强

    1.GCD串行队列和并发队列 2.GCD延时执行 3.GCD线程组:(的作用) 4.GCD定时器: GCD的实现 ...

网友评论

      本文标题:GCD

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