gcd相关

gcd(纯C语言,面向任务和队列)优势:
自动管理线程的生命周期

任务:要执行的操作
队列:用来存放任务

使用GCD:
定制任务-->将任务添加到队列中
gcd会自动将队列中的任务取出,放到对应的线程执行;任务的取出会自动遵循队列的FIFO原则,先进先出;

以同步(不具备开线程的能力)的方式执行任务:(当前线程中执行不会开新的线程)
dispatch_async(queue, ^{
        NSLog(@"-----%@", [NSThread currentThread]);
});

以异步的方式执行任务:
dispatch_sync(queue, ^{
        NSLog(@"-----%@", [NSThread currentThread]);
});

队列(决定了任务怎么执行)的类型:
并发队列:可以让多个任务并发执行,只在异步方式(dispatch_sync)执行中有效
串行队列:让任务一个接着一地执行(一个任务执行完成后,再执行下一个)

同步和异步主要影响:能不能开启新的线程
并发和串行主要影响:任务的执行方式(并行,串行)


gcd的基本使用:
 gcd默认已经提供了全局的并发队列
 1, dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//全局的并发队列
 // 第一个参数表示队列的优先级;
 // DISPATCH_QUEUE_PRIORITY_DEFAULT:默认
 2,将任务添加到全局队列中去异步执行
   dispatch_async(queue, ^{
        NSLog(@"-----下载图片---%@", [NSThread currentThread]);
   });  
   
  dispatch_async, dispatch_sync 与并发,同步共有四种组合:
 
 第一种组合(异步+并发队列):
/** 并发队列:会开多条线程
 *  async -- 并发队列(最常用)
 *  会不会创建线程:会,一般同时开多条
 *  任务的执行方式:并发执行
 */
- (void)asyncGlobalQueue
{
    // 获得全局的并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 将任务添加 全局队列 中去 异步 执行
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
    });
}

第二种组合(异步+串行队列) 
/**串行队列:一般只开一条线程,把所有任务放到一个线程里面执行
 *  async -- 串行队列(有时候用)
 *  会不会创建线程:会,一般只开1条线程  
 *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
 */
- (void)asyncSerialQueue 
{
    // 1.创建一个串行队列,串行队列需要自己创建 
    dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL);//第一个参数表示队列的名称(可以随便写),第二个参数表示队列初始化参数 
    // 2.将任务添加到串行队列中 异步 执行
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
    });
    
    // 3.非ARC,需要释放创建的队列
//    dispatch_release(queue);
}

组合三(并发队列+同步): 都在主线程按顺序执行
/**
 *  sync -- 并发队列
 *  会不会创建线程:不会
 *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
 *  并发队列失去了并发的功能
 */
- (void)syncGlobalQueue
{
    // 获得全局的并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 将 任务 添加到 全局并发队列 中 同步 执行
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
    });
}

组合四(同步+串行队列):
/**
 *  sync -- 串行队列
 *  会不会创建线程:不会
 *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
 */
- (void)syncSerialQueue
{
    // 创建一个串行队列
    dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL);
    
    // 将 任务 添加到 串行队列 中 同步 执行
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
    });
}

注意:组合三和组合四一般不使用;

gcd有两种方式获得串行队列:
1,通过dispatch_queue_create创建
2,使用主队列(会自动放在主线程中执行),通过dispatch_get_main_queue()获得;

/**
 *   异步+主队列(添加到主队列中的任务,都会自动放到主线程中去执行) 
 *  async -- 主队列示例(很常用)
 */
- (void)asyncMainQueue//不会开新线程,一般用于线程间通信,通知主线程更新ui
{
    // 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    // 2.添加 任务 到主队列中 异步 执行
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
    });
}
 
/**<span style="color:#FF0000;"> 同步+主队列:会导致主线程阻塞</span>
 *  sync -- <span style="color:#FF0000;">主队列(不能用---会卡死)</span>
 */
- (void)syncMainQueue
{
    NSLog(@"syncMainQueue----begin--");
    
    // 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    // 2.添加 任务 到主队列中 异步 执行
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
    });
    
    NSLog(@"syncMainQueue----end--");
}

foundation与core foundation类型相互转换:
NSString *str = @"123"; // Foundation
CFStringRef str2 = (__bridge CFStringRef)str; // 函数中没有create,copy,retain,不需要进行release
NSString *str3 = (__bridge NSString *)str2;

<span style="color:#FF0000;"><span style="background-color: rgb(255, 255, 255);">// Core Foundation中手动创建的数据类型,都需要手动释放</span></span>
//    CFArrayRef array = CFArrayCreate(NULL, NULL, 10, NULL);
//    CFRelease(array);

//    CGPathRef path = CGPathCreateMutable();
//    CGPathRetain(path);
//
//    CGPathRelease(path);
//    CGPathRelease(path);

<span style="color:#FF0000;"> 凡是函数名中带有create\copy\new\retain等字眼, 都应该在不需要使用这个数据的时候进行release
 GCD的数据类型在ARC环境下不需要再做release
 CF(Core Foundation)的数据类型在ARC\MRC环境下都需要再做release</span>
 
ARC:自动内存管理   MRC:手动内存管理

GCD线程间的通信:
#define HMGlobalQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define HMMainQueue dispatch_get_main_queue()
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    dispatch_async(HMGlobalQueue, ^{//异步+并发队列
        NSLog(@"donwload---%@", [NSThread currentThread]);
        // 1.子线程下载图片
        NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:data];
        
        // 2.回到主线程设置图片
        dispatch_async(HMMainQueue, ^{//异步+全局队列,通知主线程更新ui
            NSLog(@"setting---%@ %@", [NSThread currentThread], image);
            [self.button setImage:image forState:UIControlStateNormal];//按钮需要自定义的样式才能设置image
        });
    });
}
gcd延时执行:
- (void)delay3//方法一:
{
    // 3秒后回到主线程执行block中的代码
//    dispatch_queue_t queue = dispatch_get_main_queue();
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
//        NSLog(@"------task------%@", [NSThread currentThread]);
//    });
    
    // 3秒后自动开启新线程 执行block中的代码
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
        NSLog(@"------task------%@", [NSThread currentThread]);
    });
}

- (void)delay2//方法二:
{
    // 一旦定制好延迟任务后,不会卡主当前线程
    [self performSelector:@selector(download:) withObject:@"http://555.jpg" afterDelay:3];
}

- (void)delay1//方法三:
{
    // 延迟执行不要用sleep,坏处:卡住当前线程
    [NSThread sleepForTimeInterval:3];
    NSLog(@"-----下载图片-----");
}

gcd一次性代码:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"----touchesBegan");
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"----once");
        HMImageDownloader *downloader = [[HMImageDownloader alloc] init];
        [downloader download];
    });
}

oc语法:<span style="color:#FF0000;">属性名不要以new开头</span>(new是一个特殊的创建对象本身的方法),否则连线后,程序无法运行
        只有在init开头的构造方法中(以init开头的方法表示对自身进行初始化),才允许对self进行赋值

 
 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值