zoukankan      html  css  js  c++  java
  • GCD基础知识总结

    iOS三种多线程编程技术:
    1.NSThread
    2.NSOperation
    3.GCD(Grand Central Dispatch)
    从上到下,抽象度层次从低到高,抽象度越高的使用越简单,也是Apple最推荐使用的
     
    1.NSThread 需要自己管理线程的生命周期、线程同步。线程同步对数据的加锁会有一定的系统开销(他比其他两个轻量级)
    2.NSOperation 不需要关心线程管理,数据同步的事,可以把精力放在自己需要执行的操作上

    GCD概念简单理解

    GCD是基于C的Api。不需要自己管理线程生死。只需要创建队列,把任务放进队列里面就可以了。看上去很简单,其实也是有一段心酸路。

     
    GCD有两个核心概念。一个是任务,一个是队列。

    同步函数:在当前线程中执行,不开启新的线程

     
    dispatch_sync(dispatch_queue_t queue, dispatch_block_tblock);

    异步函数:具备开启线程的能力。

     
    dispatch_async(dispatch_queue_t queue, dispatch_block_tblock);
    队列

    并发队列

     
    自动开启多个线程,并且可以让多个任务同时执行。
     
    仅仅在异步函数(dispatch_async)下有效。

    串行队列

     
    让线程一个接着一个的执行。一条线程执行完后再执行下一条线程。
    并发队列

    并发队列不需要手动创建。以下是创建代码。

    dispatch_queue_tdispatch_get_global_queue(
    dispatch_queue_priority_tpriority,// 队列的优先级
    unsignedlongflags);// 此参数暂时无用,用0即可
    dispatch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//获得全局并发队列
    
    全局并发队列的优先级
    #defineDISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
    #defineDISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)
    #defineDISPATCH_QUEUE_PRIORITY_LOW (-2)// 低
    #defineDISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台
    
    
    串行队列
    使用dispatch_queue_create函数创建串行队列
    dispatch_queue_t
    dispatch_queue_create(constchar*label, //队列名称
    dispatch_queue_attr_tattr);//队列属性,一般用NULL即可
    dispatch_queue_tqueue = dispatch_queue_create("isQueue", NULL);//创建
    dispatch_release(queue);//非ARC时候需要释放手动创建的队列
    
    使用主队列(跟主线程相关联的队列)
    主队列是GCD自带的一种特殊的串行队列
    放在主队列中的任务,都会放到主线程中执行
    使用dispatch_get_main_queue()获得主队列
    dispatch_queue_tqueue = dispatch_get_main_queue();
    
    

    使用dispatch_sync同步函数时候,在主线程中往主队列添加任务会造成死锁

    队列与任务的结合
    函数全局并发队列手动创建串行队列主队列
    同步 (sync) 没有开启新线程 串行执行任务 没有开启新线程 串行执行任务 没有开启新线程 串行执行任务
    异步 (async) 有开启新线程 并发执行任务 有开启新线程 串行执行任务 没有开启新线程 串行执行任务
    线程间的通讯

    更新UI,数据等都是要回到主线程的。不能在子线程。

    //获取全局队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(queue, ^{
    
            NSLog(@"-子线程-- 开始下载图片--%@",[NSThread currentThread]);
    
            //下载数据是耗时操作放到子线程
            UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/b219ebc4b74543a94369f4cb1c178a82b9011442.jpg"]]];
    
                dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"-主线程-- 刷新UI--%@",[NSThread currentThread]);
                //回到主线程刷新UI
                self.imageView.image = image;
            });
        });
    
    
    延时操作

    延时操作不会堵塞当前线程.

    //延迟操作
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)),//从什么时候开始,是一个固定的算法
                       dispatch_get_main_queue(),//队列
                       ^{
            //做要做的操作
        });
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    
    #pragma mark 延迟操作创建一
        //获取全局队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
        //延时多久
        dispatch_time_t whenTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
    
        //延时操作,根据whenTime设计的时间
        dispatch_after(whenTime, queue, ^{
            NSLog(@"倒计时结束");
    
            dispatch_async(queue, ^{
                NSLog(@"-子线程-- 开始下载图片--%@",[NSThread currentThread]);
    
                //下载数据是耗时操作放到子线程
                UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/b219ebc4b74543a94369f4cb1c178a82b9011442.jpg"]]];
    
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSLog(@"-主线程-- 刷新UI--%@",[NSThread currentThread]);
    
                    //回到主线程刷新UI
                    self.imageView.image = image;
    
                });
            });
        });
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    
    #pragma mark 延迟操作创建二
        //获取全局队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    
            NSLog(@"倒计时结束");
    
            dispatch_async(queue, ^{
                NSLog(@"-子线程-- 开始下载图片--%@",[NSThread currentThread]);
    
                //下载数据是耗时操作放到子线程
                UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/b219ebc4b74543a94369f4cb1c178a82b9011442.jpg"]]];
    
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSLog(@"-主线程-- 刷新UI--%@",[NSThread currentThread]);
    
                    //回到主线程刷新UI
                    self.imageView.image = image;
                });
            });
        });
    
    
    GCD一次性代码
    static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
                //代码只执行一次
        });
    });
    
    
    GCD队列组
    分组模式 dispatch_group_notify

    可以异步执行多个耗时操作。等耗时操作都执行完毕之后会回到主线程执行操作。主要用于监听任务是否完成。

    //获取全局队列
        dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //创建一个队列组
        dispatch_group_t group = dispatch_group_create();
    
        dispatch_group_async(group, globalQueue, ^{
    
            NSLog(@"--- 1 开始--- %@",[NSThread currentThread]);
            //延时5秒 模仿堵塞子线程
            [NSThread sleepForTimeInterval:5];
            NSLog(@"--- 2 --- 完成 %@",[NSThread currentThread]);
    
        });
    
        dispatch_group_async(group, globalQueue, ^{
    
            NSLog(@"--- 2 开始--- %@",[NSThread currentThread]);
            //延时5秒 模仿堵塞子线程
            [NSThread sleepForTimeInterval:5];
            NSLog(@"--- 2 --- 完成 %@",[NSThread currentThread]);
    
        });
    
        //在这个队列组里面,会等group中的全部代码执行完毕再去执行其它的操作
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    
            // 等前面的异步操作都执行完毕后,回到主线程...
            NSLog(@"全部完成");
    
        });
    
        //非ARC时候要释放掉
        //dispatch_release(group);
    
    
    dispatch_apply组内无序循环执行任务
    //循环执行任务,并且执行任务的顺序是无序列的。这里会堵塞当前的线程。所以要注意。一般都是在子线程中执行。
    dispatch_apply(size_t iterations,//执行的次数
                       <#dispatch_queue_t queue#>,//队列
                       <#^(size_t)block#>)//任务
        dispatch_apply(5, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
            NSLog(@"%zu",index);
        });
    
    
    dispatch_set_target_queue 变更queue的优先级别
    dispatch_queue_t exampleQueue = dispatch_queue_create("com.example.queue", NULL);     //设置这个全局并发队列的优先级为后台     dispatch_queue_t globalQueued = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);     dispatch_set_target_queue(exampleQueue, globalQueued);     /**      *  经过转换之后exampleQueue的优先级别变成后台      */

    您的资助是我最大的动力!
    金额随意,欢迎来赏!

    如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的推荐按钮。
    如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的关注我

    如果,想给予我更多的鼓励,求打

    因为,我的写作热情也离不开您的肯定支持,感谢您的阅读,我是【往事亦如风】!

  • 相关阅读:
    ASCII码对照表 And HTML字符实体
    操作系统自带命令查看文件的哈希
    HMAC简介及HMAC-SHA256实现Demo
    CSV文件注入漏洞简析
    Kubernetes集群的安全机制
    Kubernetes -- Horizontal Pod Autoscaler
    获取两坐标之间距离
    在CentOS 7中搭建Git服务器
    centos7 搭建svn服务器
    node.js依赖express解析post请求四种数据格式()
  • 原文地址:https://www.cnblogs.com/ldnh/p/5276312.html
Copyright © 2011-2022 走看看