多线程之GCD(Grand Central Dispatch)

GCD是纯C语言,但又溶有面向对象思想、基于Block。

1、GCD优点:

  • 易用:GCD比thread更简单易用,基于Block的特性导致它能极为简单的在不同代码作用域之间传递上下文。
  • 效率:GCD在很多地方比之专门创建消耗资源的线程更实用、快速。
  • 性能:GCD自动根据系统负载来增减线程数量,减少了上下文切换以及提高了计算效率。

2、GCD的使用

2.1.dispatch async异步操作

2.1.1.定义想要执行的操作(任务),追加到适当的队列中(Dispatch Queue)

2.12.Queue类型:

(1)Serial Dispatch Queue — 等待现在正在执行的任务处理结束(串行)

(2)Concurrent Dispatch Queue — 不等待现在正在执行的任务处理结束(并行、并发)

2.1.3.自己定义queue,把任务加到自定义的queue之中

(1)创建queue

 //第一个参数:给队列起名字
 //第二个参数:queue的类型 (默认是串行的)
    dispatch_queue_t queue1 = dispatch_queue_create("com.wxhl.gcd.Queue1", NULL);

    dispatch_queue_t queue2 = dispatch_queue_create("com.wxhl.gcd.Queue2", DISPATCH_QUEUE_CONCURRENT);  //并行的queue

(2)创建要执行的任务,加到queue中执行

 dispatch_async(queue2, ^{
        for (int i = 0; i < 50; i ++) {
            NSLog(@"GCD : %d", i);
        }
    });

2.1.4.使用系统给提供的queue(推荐)

两种

Main Dispatch Queue Global Dispatch Queue

串行(主线程) 并行

 //main
    dispatch_queue_t mainQueue = dispatch_get_main_queue();

    dispatch_async(mainQueue, ^{
        ;
    });

    //global
    //参数一:优先级
    //参数二:标识符
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(globalQueue, ^{

        //请求网络数据

        //显示在UI界面上
        dispatch_async(dispatch_get_main_queue(), ^{
            //UI相关的代码
        });

    });

    //主线程
    for (int i = 0; i < 50; i ++) {
        NSLog(@"主线程 : %d", i);
    }
//async: asynchronous 将任务异步的追加到队列中
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"async");
    });

2.2 dispatch sync同步操作

 //sync: synchronous 将任务同步的追加到队列中(等队列中的任务执行完,再将任务追加到队列)
    //是同步追加,不是任务同步执行,在串行队列中,任务才同步执行
    dispatch_sync(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"sync");
    });

   **dispatch_sync的问题:容易产生死锁**
    示例1:

    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"hello");
    });

    NSLog(@"主线程");

    //上述代码在主队列中执行指定的block,等待其执行结束
    //而主队列中本来就在执行上述代码,无法执行追加的block

    示例2:

    //串行的队列
    dispatch_queue_t queue = dispatch_queue_create("com.wxhl.GCD.queue", NULL);
    dispatch_async(queue, ^{
        dispatch_sync(queue, ^{
            NSLog(@"串行队列");
        });
    });

3. GCD高级用法

3.1 Dispatch After

一段时间之后,把要执行的任务追加到队列当中

- (void)viewDidLoad {
    [super viewDidLoad];

    //创建时间
    //相对的时间点     相对第一个参数多长时间之后
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);

    //时间的单位
    //NSEC_PER_SEC   秒
    //NSEC_PER_MSEC  毫秒
    //NSEC_PER_USEC  微秒

    //dispatch_time_t 指定的时间
    dispatch_after(time, dispatch_get_main_queue(), ^{
        NSLog(@"after 3s");
    });

    //第二种用法
    dispatch_after_f(dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC), dispatch_get_main_queue(), NULL, func1);

    //自己使用
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5ull * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        ;
    });

#warning 注意
    //1.不是一段时间之后执行相应的任务 (而是把要执行的任务追加到队列当中)
    //2.主线程 runloop 1/60秒检测事件, 追加的时间范围 3s - (3 + 1/60)s

}

void func1()
{

}

@end

3.2 Dispatch Group

dispatch_group_async :使用 group 监视 队列任务的执行

dispatch_group_notify:所有任务执行结束汇总,不阻塞当前线程

dispatch_group_wait: 等待直到所有任务执行结束,中途不能取消,阻塞当前线程

- (void)viewDidLoad {
    [super viewDidLoad];

 //1.创建 group
    dispatch_group_t group = dispatch_group_create();

    //2.获取队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    //3.使用 group 监视 队列任务的执行
    dispatch_group_async(group, queue, ^{
        NSLog(@"task 1");
    });

    dispatch_group_async(group, queue, ^{
        NSLog(@"task 2");
    });

    dispatch_group_async(group, queue, ^{
        NSLog(@"task 3");
    });

    dispatch_group_async(group, queue, ^{
        sleep(6);
        NSLog(@"task 4");
    });

    //(1)监视的函数
    //监视到队列里任务执行结束,执行block里面的任务
    dispatch_group_notify(group, queue, ^{
        //结束处理
        NSLog(@"done");
    });

    //(2)

    //等待time时间,根据wait函数的返回值确定队列中任务是否执行结束,5秒后汇总结果,不管任务有没有执行完
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC);

    //dispatch_group_wait 指定的时间之后 看一眼queue的任务是否执行完毕
    //如果执行完,返回0
    //如果没有执行完,返回非0值
    long result = dispatch_group_wait(group, time);
    if (result == 0) {
        NSLog(@"finish");
    } else {
        NSLog(@"not finish");
    }

    //dispatch_group_wait 会堵塞当前线程 一直在调用这个函数 等待指定的时间之后才会返回

 sleep(2);
    NSLog(@"main");
}

@end

3.3 dispatch once实现单例

ViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];

    //dispatch once
    //保证block里的任务只执行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"只会执行一次");
    });
}

@end

AddressBook.m

#import "AddressBook.h"

static AddressBook *instance = nil;

@implementation AddressBook
/*
 * 单例  单例模式  尽量不要使用
 * 1.含义:一个类只创建一个对象
 * 2.生命周期:从创建开始,应用程序退出结束
 * 3.取得单例对象的方法,命名规则: share default
 * 4.内存管理尽量由该类来管理
 */

+ (AddressBook *)sharedInstance
{
 //onceToken 标记block里的代码是否执行过
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[AddressBook alloc] init];
    });

    return instance;
}
//alloc 会自动调用 allocWithZone:
//zone 空间 分配内存空间(zone),创建对象
+ (id)allocWithZone:(NSZone *)zone
{
    if (instance == nil) {
        instance = [super allocWithZone:zone];
    }
    return instance;
}
@end

4. 小结:

  • 安全:无需加锁或其他同步机制。
  • 充分利用多核
  • 所有多线程代码集中在一起,便于维护
  • GCD中无需实用@autoreleasepool
  • 如果要顺序执行,可以使用dispatch_sync同步方法(dispatch_sync无法确定任务的执行顺序)
  • 调用主线程队列任务更新UI时,最好使用同步方法
时间: 2024-11-08 07:42:04

多线程之GCD(Grand Central Dispatch)的相关文章

iOS开发-多线程之GCD(Grand Central Dispatch)

Grand Central Dispatch(GCD)是一个强有力的方式取执行多线程任务,不管你在回调的时候是异步或者同步的,可以优化应用程序支持多核心处理器和其他的对称多处理系统的系统.开发使用的过程中只需要将执行的任务并添加到到适当的Dispatch Queue中,GCD就能生成必要的线程并计划执行任务.Dispatch Queue更简单而且在实现符合需求的多线程任务时更有效率.Dispatch  Queue一般来说有三种方式,如下图: Serial执行的时候的先进先出,Concurrent

GCD (Grand Central Dispatch) 笔记

GCD (Grand Central Dispatch) 是Apple公司开发的一种技术,它旨在优化多核环境中的并发操作并取代传统多线程的编程模式. 在Mac OS X 10.6和IOS 4.0之后开始支持GCD. 使用GCD的一个理由就是方便.回想一下以前的多线程编程,我们会把异步调用的代码放到另外的一个函数中,并通过NSThread开启新线程来启动这段代码. 这种跳来跳去的流程对于复杂的逻辑简直就是一场灾难.更糟糕的是,调用线程时的环境对异步代码是不可见的,如果我们需要当时的临时变量的话只有

GCD Grand central Dispatch

上一章我们讨论了iOS中的网络部分的进程线程多线程的相关知识,并且初步了解了NSThread的操作.但是NSThread是有问题的.比如在某个实例,我们需要在当tableView 中显示许多的cell,而cell上是来自网络加载的图片数据.那么我们需要在代理方法中调用cell的时候对imageView添加图片.传统的UIImageView的setImage方法是在主线程中执行的.图片较少的情况下是看不出什么卡顿的效果.但是如果图片的数量很多的情况下如果不使用cell复用,xib下显示100张图片

iOS Grand Central Dispatch(GCD) 的简单理解

引言: GCD的全称是Grand Central Dispatch,是苹果在iOS4.0发布的一套处理并发运算方面的API.其用途是为了提高处理器多核运算的能力. GCD有点像NSOperationQueue,它们都允许程序将任务切分为多个单一任务然后提交至工作队列来并发地或者串行地执行,但GCD比之NSOpertionQueue更底层更高效. GCD的工作原理: GCD的工作原理是让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务. 一个任务可以是一个函数(

Grand Central Dispatch(GCD)

一.Grand Central Dispatch(GCD)概要 1.什么是GCD Grand Central Dispatch(GCD)是异步执行任务的技术之一. GCD用我们难以置信的非常简洁的记述方法,实现了极为复杂繁琐的多线程编程. 例如: dispatch_async(queue, ^{ //长时间处理 //例如AR用动画识别 //例如数据库访问 //长时间处理结束,主线程使用该处理结果 dispatch_async( dispatch_get_main_queue(), ^{ //只在

iOS学习篇之Grand Central Dispatch(GCD)

我这里做一个简单的记录,担心现在看完了如果不做记录将来还得重头看,太浪费时间了. 全文翻译可谓是漏斗百出,将就着理解一下吧. 一些比较通俗易懂的文章推荐: GCD (Grand Central Dispatch) 笔记.Grand Central Dispatch(GCD).block && Grand Central Dispatch) 原文地址:Grand Central Dispatch (GCD) Reference CGD包含语法特征(直译是语法特征/功能),运行时库和系统增强即

OC多线程之GCD

要了解多线程首先要知道什么是进程,什么是进程? 正在进行中的程序被称为进程,负责程序运行的内存分配 每一个进程都有自己独立的虚拟内存空间 什么是线程: 线程是进程中一个独立的执行路径(控制单元) 一个进程中至少包含一条线程,即主线程 可以将耗时的执行路径(如:网络请求)放在其他线程中执行 创建线程的目的就是为了开启一条新的执行路径,运行指定的代码,与主线程中的代码实现同时运行 线程的优缺点: 优势 (1)充分发挥多核处理器优势,将不同线程任务分配给不同的处理器,真正进入“并行运算”状态 (2)将

(五十五)iOS多线程之GCD

GCD的全称为Grand Central Dispatch,翻译为大中央调度,是Apple开发的一个多线程编程解决方法. 进程和线程的概念: 正在进行中的程序被称为进程,负责程序运行的内存分配,每一个进程都有自己独立的虚拟内存空间. 线程是进程中一个独立的执行路径,即主线程,主线程有1M的栈区,对于耗时的执行路径,可以放在子线程(512K栈区)中执行. Tip:新建线程会消耗内存空间和CPU事件,线程太多会降低系统的运行性能,多线程是通过CPU时分复用实现的. Tip:多线程是为了并发执行多项任

iOS开发多线程之GCD

- (void)viewDidLoad { [super viewDidLoad]; /*GCD:Grand Central Dispatch 牛逼的中枢调度器,自动管理线程的生命周期(创建 调度 销毁).将任务存放到队列中,GCD会自动将队列中的任务取出,先进先出,放到线程中执行. 同步执行任务:在当前线程中执行 dispatch_sync(dispatch_queue_t queue,dispatch_block_t block) 异步执行任务:在其他线程执行 dispatch_async(

IOS中的多线程之GCD

在ios中,使用多线程有三种方式,分别是:NSThread.NSOperation和NSOperationQueue.GCD,在本节,主要讲解一下CDD的使用. GCD(Grand Central Dispatch) ,他是基于C语言开发的一套多线程开发机制,也是目前苹果官方推荐的多线程开发方法.GCD的抽象层次最高,用起来比较简单,但是因为它是基于C语言开发的,是面向过程的,所以在使用的时候不如面向对象的好理解.但是GCD这种机制相比较于前面两种多线程开发方式最显著的优点就是它对于多核运算更加