GCD是当前多线程使用最方便的,也是使用比较多的。

学习GCD主要集中在一下几点:

一、队列,同步,异步

1.主队列:dispatch_get_main_queue();

2.串行队列:dispatch_queue_create("queue", 0);

3.并行队列:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

4.同步,异步就不需要再多说什么。

对上面关键词的一些解释:

主队列:主队列只能使用异步来执行队列中的任务,使用同步的话会造成死循环。同时执行任务的时候是在主线程中执行的。

串行队列:(1)、添加到串行队列中的任务是一个接着一个执行的,也就是当上一个任务执行完之后才开始下一个任务;

但是可以创建多个串行队列,每个串行队列之间是相互独立的,可以并发执行。

(2)、如果用同步执行的话就是在当前线程上执行;

(3)、如果用异步执行的话就是新开辟一个线程执行。

并行队列:(1)、添加到并行队列中的任务可以并发启动,启动顺序仍然是一个接着一个,但是后者可以不等前者执行完就可以开始执行。

并行队列也可以创建多个,各个之间也是相互独立,并发执行的。

(2)、如果用同步执行的话就是在当前线程上执行;

(3)、如果用异步执行的话就是新开辟一个线程执行。

二、经常用到的地方

1.任务执行完毕之后再进行一些操作

2.只执行一次

3.延时操作

对上面用处的一些解释:

(1)、任务执行完毕之后再进行一些操作,如果是一些简单的操作可以直接使用串行队列实现。但是一些比较费时的操作就需要用到队列组了。

//1.创建一个队列组
        dispatch_group_t group = dispatch_group_create();
    
    //2.开启一个任务1
    dispatch_group_async(group, global_quque, ^{
 
    });
    
    //3.开启一个任务2
    dispatch_group_async(group, global_quque, ^{

});
    
   //4.等group中的所有任务都执行完毕, 再回到主线程执行其他操作
    dispatch_group_notify(group,main_queue, ^{
     });

(2)、只执行一次

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

// 只执行1次的代码(这里面默认是线程安全的)

});

(3)、延时操作

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

//延迟执行的方法

});

(4)、暂停和恢复队列中的任务

dispatch_suspend和dispatch_resume

我们知道NSOperationQueue有暂停(suspend)和恢复(resume)。其实GCD中的队列也有类似的功能。用法也非常简单:

dispatch_suspend(queue) //暂停某个队列

dispatch_resume(queue)  //恢复某个队列

这些函数不会影响到队列中已经执行的任务,队列暂停后,已经添加到队列中但还没有执行的任务不会执行,直到队列被恢复。

(5)、承上启下

dispatch_async(queue, block1_for_reading)

dispatch_async(queue, block2_for_reading)

dispatch_barrier_async(queue, block_for_writing)

dispatch_async(queue, block3_for_reading)

dispatch_async(queue, block4_for_reading)

dispatch_barrier_async 会把并行队列的运行周期分为这三个过程:

  1. 首先等目前追加到并行队列中所有任务都执行完成
  2. 开始执行 dispatch_barrier_async 中的任务,这时候即使向并行队列提交任务,也不会执行
  3. dispatch_barrier_async 中的任务执行完成后,并行队列恢复正常。

总的来说,dispatch_barrier_async 起到了“承上启下”的作用。它保证此前的任务都先于自己执行,此后的任务也迟于自己执行。正如barrier的含义一样,它起到了一个栅栏、或是分水岭的作用。

这样一来,使用并行队列和 dispatc_barrier_async 方法,就可以高效的进行数据和文件读写了。

(6)、信号量

dispatch_semaphore

首先介绍一下信号量(semaphore)的概念。信号量是持有计数的信号,不过这么解释等于没解释。我们举个生活中的例子来看看。

假设有一个房子,它对应进程的概念,房子里的人就对应着线程。一个进程可以包括多个线程。这个房子(进程)有很多资源,比如花园、客厅等,是所有人(线程)共享的。

但是有些地方,比如卧室,最多只有两个人能进去睡觉。怎么办呢,在卧室门口挂上两把钥匙。进去的人(线程)拿着钥匙进去,没有钥匙就不能进去,出来的时候把钥匙放回门口。

这时候,门口的钥匙数量就称为信号量(Semaphore)。很明显,信号量为0时需要等待,信号量不为零时,减去1而且不等待。

在GCD中,创建信号量的语法如下:

var semaphore = dispatch_semaphore_create(2)

这句代码通过 dispatch_semaphore_create 方法创建一个信号量并设置初始值为 2。然后就可以调用 dispatch_semaphore_wait 方法了。

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)

dispatch_semaphore_wait 方法表示一直等待直到信号量的值大于等于 1,当这个方法执行后,会把第一个信号量参数的值减 1。

第二个参数是一个 dispatch_time_t 类型的时间,它表示这个方法最大的等待时间。这在第一章中已经讲过,比如 DISPATCH_TIME_FOREVER 表示永久等待。

返回值也和 dispatch_group_wait 方法一样,返回 0 表示在规定的等待时间内第一个参数信号量的值已经大于等于 1,否则表示已超过规定等待时间,但信号量的值还是 0。

dispatch_semaphore_wait 方法返回 0,因为此时的信号量的值大于等于一,任务获得了可以执行的权限。这时候我们就可以安全的执行需要进行排他控制的任务了。

任务结束时还需要调用 dispatch_semaphore_signal() 方法,将信号量的值加 1。这类似于之前所说的,从卧室出来要把锁放回门上,否则后来的人就无法进入了。

我们来看一个完整的例子:

var semaphore = dispatch_semaphore_create(1)

let queue = dispatch_queue_create("com.gcd.kt", DISPATCH_QUEUE_CONCURRENT)

var array: [Int] = []

for i in 1...100000 {

dispatch_async(queue, { () -> Void in

/*

某个线程执行到这里,如果信号量值为1,那么wait方法返回1,开始执行接下来的操作。

与此同时,因为信号量变为0,其它执行到这里的线程都必须等待

*/

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)

/*

执行了wait方法后,信号量的值变成了0。可以进行接下来的操作。

这时候其它线程都得等待wait方法返回。

可以对array修改的线程在任意时刻都只有一个,可以安全的修改array

*/

array.append(i)

/*

排他操作执行结束,记得要调用signal方法,把信号量的值加1。

这样,如果有别的线程在等待wait函数返回,就由最先等待的线程执行。

*/

dispatch_semaphore_signal(semaphore)

})

}

总结:

1、常用的延时操作:

(1)    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

//延迟执行的方法

});

(2)   [self performSelector:@selector(test) withObject:nil afterDelay:1.0];

2、回到主线程的操作:

(1)    dispatch_async(dispatch_get_main_queue(), ^{

// 回到主线程,执⾏UI刷新操作 });

(2)    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];

转载于:https://www.cnblogs.com/danMing-love/p/5598361.html

关于多线程之GCD的一些学习要点相关推荐

  1. iOS多线程之GCD小记

    iOS多线程之GCD小记 iOS多线程方案简介 从各种资料中了解到,iOS中目前有4套多线程的方案,分别是下列4中: 1.Pthreads 这是一套可以在很多操作系统上通用的多线程API,是基于C语言 ...

  2. iOS 线程之GCD的高级使用方法

    之前的一篇关于线程的blog已经为大家介绍了GCD的简单使用方式及样例说明,今天因为项目中有特殊的应用GCD的实例,为大家介绍两种特殊需求的使用GCD的方法. 目的:实现一件事情做完,再做下一件事情. ...

  3. (五十五)iOS多线程之GCD

    GCD的全称为Grand Central Dispatch,翻译为大中央调度,是Apple开发的一个多线程编程解决方法. 进程和线程的概念: 正在进行中的程序被称为进程,负责程序运行的内存分配,每一个 ...

  4. IOS中的多线程之GCD

    在ios中,使用多线程有三种方式,分别是:NSThread.NSOperation和NSOperationQueue.GCD,在本节,主要讲解一下CDD的使用. GCD(Grand Central D ...

  5. linux 线程pthread_detach,linux线程之pthread_join和pthread_detach

    在任何一个时间点上,线程是可结合的(joinable)或者是分离的(detached).一个可结合的线程能够被其他线程收回其资源和杀死.在 被其他线程回收之前,它的存储器资源(例如栈)是不释放的.相反 ...

  6. 多线程之NSThread

    关于多线程会有一系列如下: 多线程之概念解析 多线程之pthread, NSThread, NSOperation, GCD 多线程之NSThread 多线程之NSOperation 多线程之GCD ...

  7. Android多线程之ArrayBlockingQueue源码解析

    阻塞队列系列 Android多线程之LinkedBlockingQueue源码解析 Android多线程之SynchronousQueue源码解析 Andorid多线程之DelayQueue源码分析 ...

  8. Asp.Net Core 轻松学-多线程之Task快速上手

    Asp.Net Core 轻松学-多线程之Task快速上手 原文:Asp.Net Core 轻松学-多线程之Task快速上手 前言     Task是从 .NET Framework 4 开始引入的一 ...

  9. JAVA多线程之wait/notify

    本文主要学习JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法. ①wait() 与 notify/notifyAll 方法必须在同步代码块中使用 ②wait ...

最新文章

  1. Assembly--软件PBcR和Canu
  2. java如何实现python的urllib.quote(str,safe='/')
  3. Java:由浅入深揭开 AOP 实现原理
  4. libreoffice
  5. 文件句柄(file handles) 文件描述符(file descriptors)
  6. Java基础学习总结(24)——Java单元测试之JUnit4详解
  7. matlab暂态信号,MATLAB6在电力暂态波形仿真实现中的应用
  8. 天津科技大学计算机基础,天津科技大学大学计算机基础样卷
  9. 部署 dashboard 插件
  10. 中兴被逼入绝境,或将出售手机业务?
  11. 数据降维降维(二)----Laplacian Eigenmaps
  12. C#反编译工具:ILSpy
  13. NotifyIcon的属性、事件、方法
  14. 4X99神将X国逆向工程实战
  15. php实现阳历阴历互转的方法
  16. 传奇人物李兴平5000万卖掉hao123后在做什么
  17. Coding哥,魅族让你用洪荒之力来夺宝了!
  18. 苹果或引爆NFC支付潮 关注国内概念板块
  19. java.打印菱形_利用java程序打印空菱形
  20. 用ENSP华为模拟器配置一个完整的校园网

热门文章

  1. 判断一个无符号整数是不是2的n次幂的幂
  2. minicom/picocom/cutecom/putty 安装与使用教程
  3. javascript学习系列(10):数组中的slice方法
  4. 前端学习(3178):ant-design介绍1
  5. [html] 举例说明使用data-有什么优点?
  6. 前端学习(2865):公开课封装组件库介绍
  7. 前端学习(2695):重读vue电商网站16之Upload 上传组件
  8. 前端学习(2608):vuex的介绍
  9. 前端学习(2341):jsx的本质
  10. “约见”面试官系列之常见面试题之第六十二篇之IE和兼容下写法(建议收藏)