zoukankan      html  css  js  c++  java
  • IOS中级篇 —— 多线程 GCD

    GCD 是c语言的框架,不需要手动管理内存
     
    是一个面向任务   不是面向线程,不需要管理线程的生命周期
     
    GCD 任务/队列 执行函数
    任务:Block  任务都封闭在Block中。  —— 线程执行
     
    队列:存放任务    FIFO (先进先出的原则)
            GCD中的队列:
                                      串行队列:想要任务按顺序执行
    //    创建一个串行队列
        dispatch_queue_t serialQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
                                      并发队列:想要任务并发执行(同时执行)
    //    创建一个并发队列
        dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
    两个特殊队列
              主队列:主队列中存放的任务最终会交给主线程来执行。
    //    获取主队列  不需要创建
        dispatch_queue_t mainQueue = dispatch_get_main_queue();
              全局并发队列:也是并发队列 没有任何区别。 平常开发用非常多。 (不需要管理 程序需要开多少条线程。 会按照当前的设备来自动开线程          
    //    获取全局并发队列  不需要创建
    //    long identifier  ios8之前 传线程优先级 DISPATCH_QUEUE_PRIORITY_DEFAULT   ios8以后传0 可以兼容之前的版本
    //    <#unsigned long flags#> 保留接口 还未用  传 0
        dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
     
    执行函数: 将队列中的任务放到线程中执行
                        同步执行函数:不具备开启新线程的能力。任务中会在当前线程执行。
    //      同步
        dispatch_sync(concurrentQueue, ^{
            NSLog(@"下载图片2");
        });
    同步函数 + 并发队列 和 + 串行队列 效果是一样的
     
                        异步执行函数:具备开启新线程能力。 是否开启线程不一定。 与队列有关
    //    执行函数
    //      异步执行
    //      dispatch_queue_t queue 队列
    //      ^(void)block    任务
        dispatch_async(serialQueue, ^{
            NSLog(@"下载图片");
        });
     
    GCD的作用:
         1>将任务添加到队列中
         2>用执行函数执行任务中的任务 
    2个执行函数 * 3个队列 
     

    同步函数例子

     1 // 同步函数 + 串行队列
     2 // 不会开启新线程,任务是在当前线程执行.
     3 // 如果当前线程是子线程的话,就是在子线程执行
     4 // 任务是按顺序执行的
     5 -(void)test1
     6 {
     7     dispatch_queue_t serialQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL);
     8     // 同步函数
     9     dispatch_sync(serialQueue, ^{
    10         // 任务
    11         NSLog(@"下载图片1%@",[NSThread currentThread]);
    12     });
    13     // 同步函数
    14     dispatch_sync(serialQueue, ^{
    15         // 任务
    16         NSLog(@"下载图片2%@",[NSThread currentThread]);
    17     });
    18     // 同步函数
    19     dispatch_sync(serialQueue, ^{
    20         // 任务
    21         NSLog(@"下载图片3%@",[NSThread currentThread]);
    22     });
    23 }
    24  
    25 // 同步函数 + 全局并发队列
    26 // 不会开启新线程,在当前线程执行
    27 // 如果当前线程是子线程的话,就是在子线程执行
    28 // 任务按顺序执行
    29 - (void)test2
    30 {
    31     dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    32     dispatch_sync(queue, ^{
    33         NSLog(@"下载图片1%@",[NSThread currentThread]);
    34     });
    35     dispatch_sync(queue, ^{
    36         NSLog(@"下载图片2%@",[NSThread currentThread]);
    37     });
    38     dispatch_sync(queue, ^{
    39         NSLog(@"下载图片3%@",[NSThread currentThread]);
    40     });
    41 }
    42 // 对于同步函数 + 串行队列 和 +并发队列 执行效果是一样的.
    43 // 同步函数 +主队列
    44 // 主队列中的任务都会交给主线程来执行.
    45 // 主线程中的任务和主队列中的任务相互等待,无法执行完毕
    46 - (void)test3
    47 {
    48     dispatch_sync(dispatch_get_main_queue(), ^{
    49         NSLog(@"下载图片1%@",[NSThread currentThread]);
    50     });
    51     dispatch_sync(dispatch_get_main_queue(), ^{
    52         NSLog(@"下载图片2%@",[NSThread currentThread]);
    53     });
    54     dispatch_sync(dispatch_get_main_queue(), ^{
    55         NSLog(@"下载图片3%@",[NSThread currentThread]);
    56     });
    57     NSLog(@"test3End%@",[NSThread currentThread]);
    58 
    59 }

    异步函数例子  

     
     1 // 异步函数 + 主队列
     2     // 不会开启新线程
     3     // 任务按顺序执行
     4     // 不会卡死主线程
     5     dispatch_async(dispatch_get_main_queue(), ^{
     6 
     7         NSLog(@"下载图片1%@", [NSThread currentThread]);
     8     });
     9     // 异步函数 + 主队列
    10     dispatch_async(dispatch_get_main_queue(), ^{
    11         NSLog(@"下载图片2%@", [NSThread currentThread]);
    12     });
    13     // 异步函数 + 主队列
    14     dispatch_async(dispatch_get_main_queue(), ^{
    15         NSLog(@"下载图片3%@", [NSThread currentThread]);
    16     });
    17  
    18 // 异步函数 + 串行队列
    19 // 开启一条新线程.
    20 // 一个队列对应一条线程.每一条线程中的任务都是按顺序执行-- 串行执行.
    21 // 如果创建了多个串行队列,会开启多条线程.
    22 - (void)test1
    23 {
    24     dispatch_queue_t queue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL);
    25     dispatch_queue_t queue1 = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL);
    26     dispatch_async(queue, ^{
    27         NSLog(@"下载图片1%@", [NSThread currentThread]);
    28     });
    29     dispatch_async(queue1, ^{
    30         NSLog(@"下载图片2%@", [NSThread currentThread]);
    31     });
    32 
    33     dispatch_async(queue1, ^{
    34         NSLog(@"下载图片3%@", [NSThread currentThread]);
    35     });
    36 
    37     dispatch_async(queue, ^{
    38         NSLog(@"下载图片4%@", [NSThread currentThread]);
    39     });
    40 } 
    41  
    42 // 异步函数 + 全局并发队列
    43 // 开启一条线程,在子线程中执行任务
    44 // 根据任务数量,开启多条线程.
    45 // GCD自动帮我们开启一定数量的线程.
    46 - (void)test2
    47 {
    48     dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    49     // 异步函数 + 全局并发队列
    50     dispatch_async(queue, ^{
    51         NSLog(@"下载图片1%@",[NSThread currentThread]);
    52     });
    53     // 异步函数 + 全局并发队列
    54     dispatch_async(queue, ^{
    55         NSLog(@"下载图片2%@",[NSThread currentThread]);
    56     });
    57 }
    58  
    59     // 一次性代码,只会执行一次,能够保证线程安全的.
    60     // 线程第一次执行完任务之后,其他线程就不会再进来了.
    61     static dispatch_once_t onceToken;
    62     dispatch_once(&onceToken, ^{
    63         NSLog(@"%@",[NSThread currentThread]);
    64         NSLog(@"一次性代码,只执行一次%@",string);
    65     });
    66  
    67    //队列组的使用
    68 -(void)groupTest
    69 {
    70     __block UIImage *image1,*image2;
    71     // 创建一个队列组
    72     dispatch_group_t group = dispatch_group_create();
    73     // 将我们需要执行的任务放在队列中里面
    74     // 异步的方法
    75     dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
    76         // 任务1
    77         NSLog(@"renwu 1");
    78         image1 = [self downloadImageWithUrlString:@"http://e.hiphotos.baidu.com/zhidao/pic/item/203fb80e7bec54e722c5454ebb389b504fc26ab0.jpg"];
    79     });
    80     // 再往队列组中添加一个任务
    81     dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
    82         // 任务2
    83         NSLog(@"renwu 2");
    84         image2 = [self downloadImageWithUrlString:@"http://www.cnwan.com.cn/uploads/allimg/2011-07/01002414-1-10j14.jpg"];   
    85     });
    86    // 队列组中的任务都执行完毕以后,会发送一个通知,执行下面的方法
    87     dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    88         // 队列组中的任务执行完毕之后的操作
    89         NSLog(@"renwu over");
    90        // 合并图片
    91         self.imageView.image = [self BingImageWith:image1 :image2]; 
    92     });
    93 }
  • 相关阅读:
    (圆形imageview 类似qq头像)---》(ps:引用第三库APAvatarImageView>
    uiscrollerview循环滚动(参考第三方库:HMBannerView)https://github.com/iunion/autoScrollBanner
    iOS -动态可变参数
    ios-UIPickerView基本使用
    iOS 实现进度条(progress)
    @property (nonatomic, getter = isExpanded) BOOL expanded;
    linker command failed with exit code 1 (use -v to see invocation)
    APICloud界面间跳转
    iOS CGRectGetMaxY/CGRectGetMaxX
    iOS UIView常用的一些方法setNeedsDisplay和setNeedsLayout 区别
  • 原文地址:https://www.cnblogs.com/deng1989/p/4595067.html
Copyright © 2011-2022 走看看