GCD的相关函数使用

Posted blue-fly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GCD的相关函数使用相关的知识,希望对你有一定的参考价值。

GCD

ios多线程实现方案之一,非常常用

英文翻译过来就是伟大的中枢调度器,也有人戏称为是牛逼的中枢调度器

是苹果公司为多核的并行运算提出的解决方案

 

1.一次性函数

dispatch_once

顾名思义是只执行一次的函数,注意是整个程序中只执行一次(单例模式常用到)

- (void)once {
    
    //一次性函数,只执行函数
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //里面默认线程安全的
        NSLog(@"------run");
    });
}

 

2.栅栏函数

dispatch_barrier_async

作用就是控制多线程的执行顺序

- (void)barrier {
    dispatch_queue_t queue = dispatch_queue_create("123", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        NSLog(@"_______1--------%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"_______2--------%@",[NSThread currentThread]);
    });
    
    //像栅栏一样,让上面的先执行完,再执行下面的
    dispatch_barrier_async(queue, ^{
        NSLog(@"----barrier-----%@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"_______3--------%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"_______4--------%@",[NSThread currentThread]);
    });
    
}

 

 

3.快速迭代函数

dispatch_apply

作用就是开启多个线程同时完成某一件事,例如同时下载多张图片

技术分享
//一般的做法
- (void)cutFromFileTo {
    //一般在子线程中做
    //创建并行队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        //起始路径
        NSString *from = @"/Users/DDZ/Desktop/From";
        //目标路径
        NSString *to = @"/Users/DDZ/Desktop/To";
        
        
        NSFileManager *mgr = [NSFileManager defaultManager];
        //获取起始路径中所有文件路径
        NSArray *subpaths = [mgr subpathsAtPath:from];
        
        for (int i = 0; i < subpaths.count; i++) {
            
            //将路径字符串进行拼接
            NSString *fromFullPath = [NSString stringWithFormat:@"%@/%@",from,subpaths[i]];
            NSString *toFullPath = [NSString stringWithFormat:@"%@/%@",to,subpaths[i]];
            
            
            [mgr moveItemAtPath:fromFullPath toPath:toFullPath error:nil];
            
        }
        NSLog(@"剪切成功");
        
    });
}
View Code
//使用快速迭代进行剪切
- (void)cutFileApply {
    //起始路径
    NSString *from = @"/Users/DDZ/Desktop/From";
    //目标路径
    NSString *to = @"/Users/DDZ/Desktop/To";
    
    
    NSFileManager *mgr = [NSFileManager defaultManager];
    //获取起始路径中所有文件路径
    NSArray *subpaths = [mgr subpathsAtPath:from];
    
    
    dispatch_apply(subpaths.count, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
        
        NSString *subpath = subpaths[index];
        //将路径字符串进行拼接
        NSString *fromFullPath = [NSString stringWithFormat:@"%@/%@",from,subpath];
        NSString *toFullPath = [NSString stringWithFormat:@"%@/%@",to,subpath];
        
        //剪切
        [mgr moveItemAtPath:fromFullPath toPath:toFullPath error:nil];

    });
    
}

 

一般的方法只能一张图片剪切完之后,再进行下一张得剪切

而使用快速迭代则可以同时进行剪切。

 

4.队列组

dispatch_group_async

与栅栏函数有相同的目的,为了控制多线程的执行顺序

例如下载两张图片之后,再将这两者合并成新的图片并显示。

必须得先下完之后才能合并吧!(顺序问题,多线程是不可控的)

技术分享
//队列组
- (void)group {
    
    //创建组
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //1.下载图片1
    dispatch_group_async(group, queue, ^{
        
        //实现下载
        NSURL *url = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/6c224f4a20a446230761b9b79c22720e0df3d7bf.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        //生成图片
        self.img1 = [UIImage imageWithData:data];
        
    });
    
    //2.下载图片2
    dispatch_group_async(group, queue, ^{
        
        //实现下载
        NSURL *url = [NSURL URLWithString:@"http://h.hiphotos.baidu.com/image/pic/item/b812c8fcc3cec3fd5b9db074d488d43f8794270b.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        self.img2 = [UIImage imageWithData:data];
        
    });
    
    //3.将图片1,图片2合成一张新的图片
    dispatch_group_notify(group, queue, ^{
        //开启新的图形上下文
        UIGraphicsBeginImageContext(CGSizeMake(200, 200));
        
        //绘制图片
        [self.img1 drawInRect:CGRectMake(0, 0, 100, 200)];
        
        [self.img2 drawInRect:CGRectMake(100, 0, 100, 200)];
        
        //取得上下文中的图片
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        
        //结束上下文
        UIGraphicsEndImageContext();
        
        //回到主线程显示图片
        dispatch_async(dispatch_get_main_queue(), ^{
            //4.将新图片显示出来
            
            self.imageView.image = image;
        });
        
    });
    

}
View Code

 

5.延时(补充)

- (void)delay {
    //延时
    NSLog(@"______");
    [self performSelector:@selector(run) withObject:nil afterDelay:2.0];
}

- (void)run {
    NSLog(@"end");
}

 

以上是关于GCD的相关函数使用的主要内容,如果未能解决你的问题,请参考以下文章

V - Maximum GCD(输入输出相关技巧)

数论小节

几个关于js数组方法reduce的经典片段

iOS 多线程:『GCD』详尽总结

GCD多线程

HDU 2588 GCD(欧拉函数)