文档章节

第02天多线程网络:(04):GCD队列组的使用

宇鸿165
 宇鸿165
发布于 2017/04/18 14:33
字数 2425
阅读 6
收藏 0

#####一、GCD队列组的使用

本次学习的知识
1.队列组
2.队列组的创建
3.队列组异步函数的使用(两种方式: 1.简单的方式。2.函数队的方式)
4.拦截通知(非阻塞拦截,阻塞拦截)
阻塞 : 当前代码没有执行完毕,下面的方法不会执行




#####二、CCD队列组的基本使用

  • 1.队列组dispatch_group_t
dispatch_group_t
  • 2.创建队列组dispatch_group_create()
dispatch_group_t group = dispatch_group_create(); // 创建一个队列组 
  • 3.队列组异步函数(简单方式)dispatch_group_async
    /**
     dispatch_group_async 内部做的事情
     1) 封装任务
     2) 添加任务到队列中
     3) 会监听任务的执行情况
     参数1: 队列组
     参数2: 队列
     参数3: 执行任务代码
     */
    dispatch_group_async(group, queue, ^{
        NSLog(@"11-- %@ -- ",[NSThread currentThread]);
    });
  • 3.1队列组异步函数(函数队的方式)dispatch_group_enter 和 dispatch_group_leave 必须要配对使用
#warning dispatch_group_enter 和 dispatch_group_leave 必须要配对使用
#pragma dispatch_group_enter
    // 3.在方法后面 的异步任务 会被纳入 到队列组的监听范围
    // 参数1 : 队列
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"11-- %@ -- ",[NSThread currentThread]);
#pragma dispatch_group_leave 离开队列组
        // 离开群组
        dispatch_group_leave(group);
    });
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"22-- %@ -- ",[NSThread currentThread]);
        dispatch_group_leave(group);
    });
  • 4.队列组拦截通知方式1(非阻塞)dispatch_notify
  dispatch_notify
    // 问题? 该方法是阻塞的吗? 同步的还是异步的
    // 内部本身是异步的
    dispatch_notify(group, queue, ^{
        NSLog(@"dispatch_notify");
    });
  • 4.1队列组拦截通知方式2(阻塞)dispatch_group_wait
  /*
     参数1 : 队列组
     参数2 : gcd的时间
     #define DISPATCH_TIME_NOW (0ull)
     #define DISPATCH_TIME_FOREVER (~0ull) 死等 死都要等
     */
    // 等待 死等,直到队列组中所有的任务执行完毕之后
    // 本身是阻塞的 (当前代码没有执行完毕,下面的方法不会执行)
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

案例 使用GCD队列组进行两张图片图片合并

image1、image2是全局的属性,用来保存内容,为了防止在block里面代码块一过,对象会销毁
imageView是一个200*200的图片控件,用来合并两张图片进行显示的


- (void)group3
{
    /*
     1.下载图片1 开启子线程
     2.下载图片2 开启子线程
     3.合成图片并显示图片 开启子线程
     */
    
// 0.获取并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    // 获取队列组
    dispatch_group_t group = dispatch_group_create();
    
    
// 1.下载图片1 开启子线程
    dispatch_group_async(group, queue,^{ // 使用队列组异步函数
//    dispatch_async(queue, ^{ // 使用异步函数
        NSLog(@"download1 --- %@",[NSThread currentThread]);
        // 1.1.确定url
        NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1494051566305&di=2797cce67f410ef9b76e5daef82ab8d7&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farchive%2F0b73ff9a3db9377d07f31964984fde836813fa33.jpg"];
        // 1.2.下载二进制数据
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        // 1.3.转换成图片
        self.image1 = [UIImage imageWithData:imageData];
    });
    
// 2.下载图片2 开启子线程
    dispatch_group_async(group, queue,^{
//    dispatch_async(queue, ^{
        NSLog(@"download2 --- %@",[NSThread currentThread]);
        // 2.1.确定url
        NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1494051566305&di=cc44c89029d82764696f39f5cb9fa88a&imgtype=0&src=http%3A%2F%2Fimg1.ph.126.net%2FjPK4fKRr6oepN5AWcRr6Fg%3D%3D%2F1872653020156151185.jpg"];
        // 2.2.下载二进制数据
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        // 2.3.转换成图片
        self.image2 = [UIImage imageWithData:imageData];
    });
    
// 3.合成图片并显示图片 开启子线程
    // 如果需要在主线程执行 那么修改一下队列的线程就行了
//    dispatch_group_notify(group, queue, ^{ // 子线程
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"combie --- %@",[NSThread currentThread]);

        // 如何合并图片 (画图)?
        // 3.1 创建图形上下文
#pragma 1.UIGraphicsBeginImageContext 创建图形上下文
        UIGraphicsBeginImageContext(CGSizeMake(200, 200));
        // 3.2 画图1 (上边)
        [self.image1 drawInRect:CGRectMake(0, 0, 200, 100)]; // 图片1的位置
        // 画完图可以进行释放掉
        self.image1 = nil;
        // 3.3 画图2 (下边)
        [self.image2 drawInRect:CGRectMake(0, 100, 200, 100)]; // 图片2的位置
        self.image2 = nil;
        
        // 3.4 根据上下文 得到一张图片
#pragma 2.UIGraphicsGetImageFromCurrentImageContext 根据上下文 得到一张图片
        /*
         UIImage * UIGraphicsGetImageFromCurrentImageContext(void);
         Description
         Returns an image based on the contents of the current bitmap-based graphics context.
         You should call this function only when a bitmap-based graphics context is the current graphics context. If the current context is nil or was not created by a call to UIGraphicsBeginImageContext, this function returns nil.
         This function may be called from any thread of your app.
         Returns
         A image object containing the contents of the current bitmap graphics context.
         Availability	iOS (2.0 and later), tvOS (9.0 and later), watchOS (2.0 and later)
         
         返回一张图片
         */
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        
        // 3.5 关闭上下文
#pragma 3.UIGraphicsEndImageContext 关闭上下文
        UIGraphicsEndImageContext();

        // 3.6 更新UI 显示图片 (当前是子线程,刷新UI需要回归主线程)
//        dispatch_async(dispatch_get_main_queue(), ^{
           
            NSLog(@"UI --- %@",[NSThread currentThread]);
            self.imageView.image = image;
//        });
        
    });
    
//    dispatch_release(group);// 自己创建的队列 iOS6之前需要进行释放
    // 栅栏函数 只能在自己创建的队列使用, 不能使用全局并发队列
    
}

code

#import "ViewController.h"

@interface ViewController ()

/** 图片1 */
@property(nonatomic, strong)UIImage *image1;
/** 图片2 */
@property(nonatomic, strong)UIImage *image2;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController
#pragma mark 队列组 (队列执行完毕 之后进行操作)
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//    [self group2];
    [self group3];
}

#pragma mark 1.队列组的简单方式
- (void)group1
{
    // 1.创建队列
    // dispatch_get_global_queue 并发队列 (开启子线程进行执行)
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
#pragma 1. 队列组  dispatch_group_t
    
    // 2.创建队列组
    dispatch_group_t group = dispatch_group_create(); // 创建一个队列组 dispatch_group_create
    
    
    // 3. 创建一个异步函数 (先往下走,执行下面才执行异步函数)
    /**
     dispatch_async 内部做的事情
     1) 封装任务
     2) 添加任务到队列中
     //    dispatch_async(queue, ^{
     //        NSLog(@"11-- %@ -- ",[NSThread currentThread]);
     //    });
     */
#pragma 2. 队列组异步函数  dispatch_group_async
    
    /**
     dispatch_group_async 内部做的事情
     1) 封装任务
     2) 添加任务到队列中
     3) 会监听任务的执行情况
     
     参数1: 队列组
     参数2: 队列
     参数3: 执行任务代码
     */
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"11-- %@ -- ",[NSThread currentThread]);
    });
    
    dispatch_group_async(group,queue, ^{
        NSLog(@"22-- %@ -- ",[NSThread currentThread]);
    });
    
    dispatch_group_async(group,queue, ^{
        NSLog(@"33-- %@ -- ",[NSThread currentThread]);
    });
#pragma 3. 队列组拦截通知  dispatch_notify
    // 拦截通知 :  当队列组中所有的任务都执行完毕的时候 回进入下面这个方法
    /**
     参数1 : 队列组
     参数2 : 队列
     参数3 : 执行完毕执行的代码
     */
    dispatch_notify(group, queue, ^{
        NSLog(@"dispatch_notify");
    });
    
    NSLog(@"-- end --");

}


#pragma mark 2.使用函数队实现
- (void)group2
{
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_t group = dispatch_group_create();

#warning dispatch_group_enter 和 dispatch_group_leave 必须要配对使用
#pragma dispatch_group_enter
    // 3.在方法后面 的异步任务 会被纳入 到队列组的监听范围
    // 参数1 : 队列
    dispatch_group_enter(group);
    
    dispatch_async(queue, ^{
        NSLog(@"11-- %@ -- ",[NSThread currentThread]);
#pragma dispatch_group_leave 离开队列组
        // 离开群组
        dispatch_group_leave(group);
    });
    
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"22-- %@ -- ",[NSThread currentThread]);
        dispatch_group_leave(group);
    });

// 拦截通知
    // 问题? 该方法是阻塞的吗? 同步的还是异步的
    // 内部本身是异步的
//    dispatch_notify(group, queue, ^{
//        NSLog(@"dispatch_notify");
//    });
    
#pragma      long dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);

// 拦截通知2
    
    /**
     long dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);
     Description
     Waits synchronously for the previously submitted block objects to complete; returns if the blocks do not complete before the specified timeout period has elapsed.
     This function waits for the completion of the blocks associated with the given dispatch group and returns when either all blocks have completed or the specified timeout has elapsed. When a timeout occurs, the group is restored to its original state.
     This function returns immediately if the dispatch group is empty (there are no blocks associated with the group).
     After the successful return of this function, the dispatch group is empty, and can be reused for additional blocks. See dispatch_group_async for more information.
     If your app isn’t using ARC, you should call dispatch_release on a dispatch group when it’s no longer needed.
     Parameters
     group
     The dispatch group to wait on. This parameter cannot be NULL.
     timeout
     When to timeout (see dispatch_time). The DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants are provided as a convenience.
     Returns
     Returns zero on success (all blocks associated with the group completed before the specified timeout) or non-zero on error (timeout occurred).
     Availability	iOS (4.0 and later), macOS (10.6 and later), tvOS (4.0 and later), watchOS (2.0 and later)
     
     参数1 : 队列组
     参数2 : gcd的时间
     
     #define DISPATCH_TIME_NOW (0ull) 从现在开始
     #define DISPATCH_TIME_FOREVER (~0ull) 死等 死都要等
     */
    // 等待 死等,直到队列组中所有的任务执行完毕之后才能执行
    // 本身是阻塞的 (当前代码没有执行完毕,下面的方法不会执行)
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"-- end --");
}


- (void)group3
{
    /*
     1.下载图片1 开启子线程
     2.下载图片2 开启子线程
     3.合成图片并显示图片 开启子线程
     */
    
// 0.获取并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    // 获取队列组
    dispatch_group_t group = dispatch_group_create();
    
    
// 1.下载图片1 开启子线程
    dispatch_group_async(group, queue,^{ // 使用队列组异步函数
//    dispatch_async(queue, ^{ // 使用异步函数
        NSLog(@"download1 --- %@",[NSThread currentThread]);
        // 1.1.确定url
        NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1494051566305&di=2797cce67f410ef9b76e5daef82ab8d7&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farchive%2F0b73ff9a3db9377d07f31964984fde836813fa33.jpg"];
        // 1.2.下载二进制数据
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        // 1.3.转换成图片
        self.image1 = [UIImage imageWithData:imageData];
    });
    
// 2.下载图片2 开启子线程
    dispatch_group_async(group, queue,^{
//    dispatch_async(queue, ^{
        NSLog(@"download2 --- %@",[NSThread currentThread]);
        // 2.1.确定url
        NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1494051566305&di=cc44c89029d82764696f39f5cb9fa88a&imgtype=0&src=http%3A%2F%2Fimg1.ph.126.net%2FjPK4fKRr6oepN5AWcRr6Fg%3D%3D%2F1872653020156151185.jpg"];
        // 2.2.下载二进制数据
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        // 2.3.转换成图片
        self.image2 = [UIImage imageWithData:imageData];
    });
    
// 3.合成图片并显示图片 开启子线程
    // 如果需要在主线程执行 那么修改一下队列的线程就行了
//    dispatch_group_notify(group, queue, ^{ // 子线程
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"combie --- %@",[NSThread currentThread]);

        // 如何合并图片 (画图)?
        // 3.1 创建图形上下文
#pragma 1.UIGraphicsBeginImageContext 创建图形上下文
        UIGraphicsBeginImageContext(CGSizeMake(200, 200));
        // 3.2 画图1 (上边)
        [self.image1 drawInRect:CGRectMake(0, 0, 200, 100)]; // 图片1的位置
        // 画完图可以进行释放掉
        self.image1 = nil;
        // 3.3 画图2 (下边)
        [self.image2 drawInRect:CGRectMake(0, 100, 200, 100)]; // 图片2的位置
        self.image2 = nil;
        
        // 3.4 根据上下文 得到一张图片
#pragma 2.UIGraphicsGetImageFromCurrentImageContext 根据上下文 得到一张图片
        /*
         UIImage * UIGraphicsGetImageFromCurrentImageContext(void);
         Description
         Returns an image based on the contents of the current bitmap-based graphics context.
         You should call this function only when a bitmap-based graphics context is the current graphics context. If the current context is nil or was not created by a call to UIGraphicsBeginImageContext, this function returns nil.
         This function may be called from any thread of your app.
         Returns
         A image object containing the contents of the current bitmap graphics context.
         Availability	iOS (2.0 and later), tvOS (9.0 and later), watchOS (2.0 and later)
         
         返回一张图片
         */
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        
        // 3.5 关闭上下文
#pragma 3.UIGraphicsEndImageContext 关闭上下文
        UIGraphicsEndImageContext();

        // 3.6 更新UI 显示图片 (当前是子线程,刷新UI需要回归主线程)
//        dispatch_async(dispatch_get_main_queue(), ^{
           
            NSLog(@"UI --- %@",[NSThread currentThread]);
            self.imageView.image = image;
//        });
        
    });
    
//    dispatch_release(group);// 自己创建的队列 iOS6之前需要进行释放
    // 栅栏函数 只能在自己创建的队列使用, 不能使用全局并发队列
    
}

@end

© 著作权归作者所有

宇鸿165
粉丝 1
博文 919
码字总数 368963
作品 0
广州
私信 提问
iOS多线程编程之三——GCD的应用

iOS多线程编程之三——GCD的应用 一、引言 在软件开发中使用多线程可以大大的提升用户体验度,增加工作效率。iOS系统中提供了多种分线程编程的方法,在前两篇博客都有提及: NSThread类进行多...

珲少
2015/05/21
340
0
iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用

iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用 目录(?)[+] 介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理...

malawo
2013/09/05
40
0
iOS 多线程总结:GCD的使用

进程与线程 进程就是一个应用程序在处理机上的一次执行过程,它是一个动态的概念,而线程是进程中的一部分,进程包含多个线程在运行。 线程是指进程内的一个执行单元,也是进程内的可调度实体...

朱敏_ITer
2017/10/08
0
0
iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用

介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统。这建立在任务并行执行的线程池模式的基础上的。它首次发...

木木情深
2014/02/19
43
0
传智播客学习笔记 网络多线程

主线程处理UI,避免耗时操作 iOS多线程技术有4种 pthread,通用技术,跨平台 c语言,程序员管理生命周期,几乎不用 NSThread 面向对象,可以直接操作线程 OC语言 程序员 管理生命周期,偶尔使...

云飞扬v5
2015/08/11
37
0

没有更多内容

加载失败,请刷新页面

加载更多

64.监控平台介绍 安装zabbix 忘记admin密码

19.1 Linux监控平台介绍 19.2 zabbix监控介绍 19.3/19.4/19.6 安装zabbix 19.5 忘记Admin密码如何做 19.1 Linux监控平台介绍: 常见开源监控软件 ~1.cacti、nagios、zabbix、smokeping、ope...

oschina130111
昨天
64
0
当餐饮遇上大数据,嗯真香!

之前去开了一场会,主题是「餐饮领袖新零售峰会」。认真听完了餐饮前辈和新秀们的分享,觉得获益匪浅,把脑子里的核心纪要整理了一下,今天和大家做一个简单的分享,欢迎感兴趣的小伙伴一起交...

数澜科技
昨天
26
0
DNS-over-HTTPS 的下一代是 DNS ON BLOCKCHAIN

本文作者:PETER LAI ,是 Diode 的区块链工程师。在进入软件开发领域之前,他主要是在做工商管理相关工作。Peter Lai 也是一位活跃的开源贡献者。目前,他正在与 Diode 团队一起开发基于区块...

红薯
昨天
43
0
CC攻击带来的危害我们该如何防御?

随着网络的发展带给我们很多的便利,但是同时也带给我们一些网站安全问题,网络攻击就是常见的网站安全问题。其中作为站长最常见的就是CC攻击,CC攻击是网络攻击方式的一种,是一种比较常见的...

云漫网络Ruan
昨天
27
0
实验分析性专业硕士提纲撰写要点

为什么您需要研究论文的提纲? 首先当您进行研究时,您需要聚集许多信息和想法,研究论文提纲可以较好地组织你的想法, 了解您研究资料的流畅度和程度。确保你写作时不会错过任何重要资料以此...

论文辅导员
昨天
44
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部