美文网首页iOS基础学习
多线程之GCD栅栏函数,GCD快速迭代,队列组

多线程之GCD栅栏函数,GCD快速迭代,队列组

作者: WenJim | 来源:发表于2017-10-31 22:15 被阅读78次

    1. GCD栅栏函数

    • 作用:只有当栅栏函数执行完毕后才能执行后面的函数
    • 需求:使用栅栏函数规定线程执行顺序
    • 注意点:栅栏函数不能使用全局并发队列

    使用案例

      // 1. 获得并发队列 
     // 栅栏函数不能使用全局并发队列
     dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_CONCURRENT);
        // 2. 异步函数
        dispatch_async(queue, ^{
            for (NSInteger i = 0; i< 100; i++) {
                NSLog(@"download ----%zd----- %@",i,[NSThread currentThread]);
            }
            
        });
        
        dispatch_async(queue, ^{
            for (NSInteger i = 0; i< 100; i++) {
                NSLog(@"download2 ----%zd----- %@",i,[NSThread currentThread]);
            }
        });
        
        
        // 栅栏函数
        dispatch_barrier_async(queue, ^{
            NSLog(@"栅栏----------");
        });
        
        
        dispatch_async(queue, ^{
            for (NSInteger i = 0; i< 100; i++) {
                NSLog(@"download3 ----%zd----- %@",i,[NSThread currentThread]);
            }
        });
        
        dispatch_async(queue, ^{
            for (NSInteger i = 0; i< 100; i++) {
                NSLog(@"download4 ----%zd----- %@",i,[NSThread currentThread]);
            }
        });
    

    2. GCD快速迭代

    for循环遍历数据,是同步的, 串行队列

    // 同步
        for (NSInteger i = 0; i < 10; i++) {
            NSLog(@"%zd-------%@",i,[NSThread currentThread]);
        }
    

    GCD快速迭代:

    开子线程和主线程一起完成遍历任务,任务的执行是并发队列

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        /*
         第一参数(<#size_t iterations#>): 要遍历的次数
         第二参数(<#dispatch_queue_t  _Nonnull queue#>): 队列(必须是并发队列)
         第三参数(<#^(size_t)block#> ^(size_t index)):  index 为索引
         */
        dispatch_apply(10, queue, ^(size_t index) {
           
            NSLog(@"%zd-------%@",index,[NSThread currentThread]);
        });
    

    主要代码示例:

    //
    //  ViewController.m
    //  02-掌握GCD的快速迭代
    //
    //  Created by wenjim on 17/10/30.
    //  Copyright © 2017年 WenJim. All rights reserved.
    //
    
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @property (nonatomic,strong) UIButton * btn;
    
    @end
    
    @implementation ViewController
    
    -(UIButton *)btn
    {
        if (!_btn) {
            _btn = [UIButton buttonWithType:UIButtonTypeCustom];
            _btn.frame = CGRectMake(self.view.frame.size.width / 2 - 25, self.view.frame.size.height / 2 - 15, 50, 30);
            [_btn setTitle:@"点击" forState:UIControlStateNormal];
            [_btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            [_btn addTarget:self action:@selector(moveGCDFile) forControlEvents:UIControlEventTouchUpInside];
            
        }
        return _btn;
    }
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        [self.view addSubview:self.btn];
    }
    
    -(void)forDemo
    {
        // 同步
        for (NSInteger i = 0; i < 10; i++) {
            NSLog(@"%zd-------%@",i,[NSThread currentThread]);
        }
    }
    
    #pragma mark - 开子线程和主线程一起完成遍历任务,任务的执行是并发的
    -(void)apply
    {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        /*
         第一参数(<#size_t iterations#>): 要遍历的次数
         第二参数(<#dispatch_queue_t  _Nonnull queue#>): 队列(并发队列)
         第三参数(<#^(size_t)block#> ^(size_t index)): 索引
         */
        dispatch_apply(10, queue, ^(size_t index) {
           
            NSLog(@"%zd-------%@",index,[NSThread currentThread]);
        });
    }
    
    #pragma mark - for 循环 移动文件夹的所有文件
    -(void)moveFile
    {
        // 1. 拿到文件路径
        NSString * formStr = @"/Users/WJim/Desktop/GITEE/DuoXianChengDeXueXi/day12/testFile";
        
        // 2.获得目标文件路径
        NSString * toStr = @"/Users/WJim/Desktop/GITEE/DuoXianChengDeXueXi/day12/toFile";
        
        // 3. 得到目录下面的所哟文件
        NSFileManager * manager = [NSFileManager defaultManager];
        
        NSArray * arr = [manager subpathsAtPath:formStr];
        NSLog(@"文件有:%@",arr);
        // 4. 遍历所有文件
            
            for (NSInteger i = 0; i < arr.count; i ++) {
                // 4.1 拼接文件全路径
    //            NSString * formFullStr = [formStr stringByAppendingString:arr[i]];
                // 在拼接的时候会自动添加/
                NSString * formFullStr = [formStr stringByAppendingPathComponent:arr[i]];
                
                NSLog(@"文件所在路径:%@",formFullStr);
                
                NSString * toFullStr = [toStr stringByAppendingPathComponent:arr[i]];
                
                NSLog(@"移动文件所在路径:%@",toFullStr);
                
                // 4.2 移动文件  formFullStr  toFullStr
                /*
                 第一个参数:要剪切文件在哪里
                 第二个参数:文件应该被存到哪个位置
                 */
                [manager moveItemAtURL:[NSURL fileURLWithPath:toFullStr] toURL:[NSURL fileURLWithPath:formFullStr] error:nil];
            }
    }
    
    #pragma mark - GCD方法 移动文件夹的所有文件
    -(void)moveGCDFile
    {
        // 1. 拿到文件路径
        NSString * formStr = @"/Users/WJim/Desktop/GITEE/DuoXianChengDeXueXi/day12/testFile";
        
        // 2.获得目标文件路径
        NSString * toStr = @"/Users/WJim/Desktop/GITEE/DuoXianChengDeXueXi/day12/toFile";
        
        // 3. 得到目录下面的所哟文件
        
        NSFileManager * manager = [NSFileManager defaultManager];
        
        NSArray * arr = [manager subpathsAtPath:formStr];
        NSLog(@"文件有:%@",arr);
        // 4. 遍历所有文件
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
        
        dispatch_apply(arr.count, queue, ^(size_t index) {
           // 4.1 拼接文件全路径
            NSString * formFullStr = [formStr stringByAppendingPathComponent:arr[index]];
            
            NSString * toFullStr = [toStr stringByAppendingPathComponent:arr[index]];
            
            // 4.2 开始移动文件
            /*
             第一个参数:要剪切文件在哪里
             第二个参数:文件应该被存到哪个位置
             */
            [manager moveItemAtURL:[NSURL fileURLWithPath:formFullStr] toURL:[NSURL fileURLWithPath:toFullStr] error:nil];
            
        });
    }
    
    @end
    

    3. 队列组

    • 有这么1种需求
    • 首先:分别异步执行2个耗时的操作
    • 其次:等2个异步操作都执行完毕后,再回到主线程执行操作

    如果想要快速高效地实现上述需求,可以考虑用队列组

    dispatch_group_t group =  dispatch_group_create();
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 执行1个耗时的异步操作
    });
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 执行1个耗时的异步操作
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 等前面的异步操作都执行完毕后,回到主线程...
    });
    

    相关文章

      网友评论

        本文标题:多线程之GCD栅栏函数,GCD快速迭代,队列组

        本文链接:https://www.haomeiwen.com/subject/uswbattx.html