• IOS GCD 浅析


     一、简单介绍
    1.队列的类型:
         1.1主队列:main queue 主线程队列,更新UI的操作。是一个串行的队列,串行队列每次只处理一个任务。
         1.2系统创建的并发队列:global queue(全局的 并行的队列),按照优先级分类。线程池提供多个线程来执行任务,所以按照FIFO的顺序并发启动、执行多个并发任务。
         1.3自定义的队列:可以根据需要创建串行队列或并发的队列。
    2.任务:
         2.1封装形式:block或C语言的的函数
         2.2添加到队列的方式:同步或异步(只对并发队列有区别)。不管是同步还是异步,如果将任务加到串行队列中都是一个接一个的执行,只有在并发队列中才有区别。
    3.特殊使用
         3.1仅执行一次            dispatch_once
         3.2延时执行               dispatch_after
         3.3成组的执行任务      dispatch_group
    4.GCD的优势

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

    GCD会自动利用更多的CPU内核(比如双核、四核)

    GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)

    程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
     二、任务和队列

    GCD中有2个核心概念

    (1)任务:执行什么操作

    (2)队列:用来存放任务  

    GCD的使用就2个步骤

    (1)定制任务

    (2)确定想做的事情
     

    将任务添加到队列中,GCD会自动将队列中的任务取出,放到对应的线程中执行

    提示:任务的取出遵循队列的FIFO原则:先进先出,后进后出
     

    三、执行任务

    1.GCD中有2个用来执行任务的函数

    说明:把右边的参数(任务)提交给左边的参数(队列)进行执行。

    (1)用同步的方式执行任务 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

    参数说明:

    queue:队列

    block:任务  

    (2)用异步的方式执行任务 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

    2.同步和异步的区别

    同步:在当前线程中执行

    异步:在另一条线程中执行
     四、队列

    1.队列的类型

    GCD的队列可以分为2大类型

    (1)并发队列(Concurrent Dispatch Queue)

    可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)并发功能只有在异步(dispatch_async)函数下才有效

    (2)串行队列(Serial Dispatch Queue)

    让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)

    2.补充说明

    有4个术语比较容易混淆:同步、异步、并发、串行

    同步和异步决定了要不要开启新的线程

    同步:在当前线程中执行任务,不具备开启新线程的能力

    异步:在新的线程中执行任务,具备开启新线程的能力

    并发和串行决定了任务的执行方式

    并发:多个任务并发(同时)执行

    串行:一个任务执行完毕后,再执行下一个任务
    ----------分割------------
    下面实现自定义队列代码(串行,并行,同步,异步):
    //
    //  ViewController.m
    //  CX-GCD
    //
    //  Created by ma c on 16/3/15.
    //  Copyright © 2016年 xubaoaichiyu. All rights reserved.
    //
    
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //自定义队列
        
        [self queueOne];
        [self queueTwo];
        [self queueThree];
        [self queueFour];
        
    }
    -(void)queueOne{
       
        //串行同步 - 按顺序执行 立即执行 不开辟新线程
        //*注意*  "xubaoaichiyu" 前不要加"@" 因为要求传入char
        dispatch_queue_t queueOne = dispatch_queue_create("xubaoaichiyu", DISPATCH_QUEUE_SERIAL);//定义为串行队列
        //同步
        NSLog(@"开始");
        dispatch_sync(queueOne, ^{
            
            NSLog(@"One->%@",[NSThread currentThread]);
            
        });
        dispatch_sync(queueOne, ^{
            
            NSLog(@"Two->%@",[NSThread currentThread]);
            
        });
        NSLog(@"结束");
        
    }
    -(void)queueTwo{
        
        //串行异步 - 按顺序实行 不立即之执行 开辟新线程
        dispatch_queue_t queueTwo = dispatch_queue_create("xubaoaichiyu", DISPATCH_QUEUE_SERIAL);
        //异步
        NSLog(@"开始");
        dispatch_async(queueTwo, ^{
            
            NSLog(@"One->%@",[NSThread currentThread]);
            
        });
        dispatch_async(queueTwo, ^{
            
            NSLog(@"Two->%@",[NSThread currentThread]);
            
        });
        dispatch_async(queueTwo, ^{
            
            NSLog(@"Three->%@",[NSThread currentThread]);
            
        });
        NSLog(@"结束");
        
    }
    -(void)queueThree{
        
        //并行同步 - 不安顺序执行 立即执行 不开辟新线程
        dispatch_queue_t queueThree = dispatch_queue_create("xubaoaichiyu", DISPATCH_QUEUE_CONCURRENT);//定义为串行队列
        //同步
        NSLog(@"开始");
        dispatch_sync(queueThree, ^{
            
            NSLog(@"One->%@",[NSThread currentThread]);
            
        });
        dispatch_sync(queueThree, ^{
            
            NSLog(@"Two->%@",[NSThread currentThread]);
            
        });
        
        NSLog(@"结束");
        
    }
    -(void)queueFour{
        
        //并行异步 - 不按顺序执行 不立即执行 开辟新空间
        dispatch_queue_t queueFour = dispatch_queue_create("xubaoaichiyu", DISPATCH_QUEUE_CONCURRENT);
        //异步
        NSLog(@"开始");
        dispatch_async(queueFour, ^{
            
            NSLog(@"One->%@",[NSThread currentThread]);
            
        });
        dispatch_async(queueFour, ^{
            
            NSLog(@"Two->%@",[NSThread currentThread]);
    
        });
        dispatch_async(queueFour, ^{
            
            NSLog(@"Three->%@",[NSThread currentThread]);
            
        });
        NSLog(@"结束");
        
    }
    
    
    @end

    分组测试结果:

    1)串行同步

    2)串行异步
     
    3)并行同步
    4)并行异步
     

    主队列及其他一些方法(这里就不实现代码了):

    //
    //  ViewController.m
    //  CX-GCD Two
    //
    //  Created by ma c on 16/3/15.
    //  Copyright © 2016年 xubaoaichiyu. All rights reserved.
    //
    
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //主队列 串行队列
        dispatch_queue_t mainQueue = dispatch_get_main_queue();
        //延迟
        dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);
        dispatch_after(time, mainQueue, ^{
            NSLog(@"我来晚了两秒");
        });
    //    dispatch_barrier_async -> 在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行.
        //异步 按顺序 不立即执行
        dispatch_async(mainQueue, ^{
            NSLog(@"a-One");
        //CGD中的单例
            [self onceToken];
        });
        dispatch_async(mainQueue, ^{
            NSLog(@"a-Two");
            [self onceToken];
        });
        dispatch_barrier_async(mainQueue, ^{
            NSLog(@"--------分割--------");
        });
        dispatch_async(mainQueue, ^{
            NSLog(@"a-Three");
            [self onceToken];
        });
        //同步 死锁
    //    NSLog(@"开始");
    //    dispatch_sync(mainQueue, ^{
    //        NSLog(@"One");
    //    });
    //    dispatch_sync(mainQueue, ^{
    //        NSLog(@"Two");
    //    });
    //    dispatch_sync(mainQueue, ^{
    //        NSLog(@"Three");
    //    });
    //    NSLog(@"结束");
    //    执行某个代码dispatch_apply(遍历)
        dispatch_queue_t queue = dispatch_queue_create("xubaoaichiyu", DISPATCH_QUEUE_SERIAL);
        dispatch_apply(5, queue, ^(size_t i) {
            
            NSLog(@"%@",@(i));
            
        });
        
    }
    
    -(void)onceToken{
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            NSLog(@"onceToken");
        });
        
    }
    
    @end

    全局队列及调度组:

    //
    //  ViewController.m
    //  CX - GCD Three
    //
    //  Created by ma c on 16/3/15.
    //  Copyright © 2016年 xubaoaichiyu. All rights reserved.
    //
    
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //全局队列
        /*
         优先级
         DISPATCH_QUEUE_PRIORITY_HIGH
         DISPATCH_QUEUE_PRIORITY_DEFAULT
         DISPATCH_QUEUE_PRIORITY_LOW
         DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
         */
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
        //调度组
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_async(group, queue, ^{
           
            [NSThread sleepForTimeInterval:3];
            NSLog(@"Ome");
            
        });
        dispatch_group_async(group, queue, ^{
            
            [NSThread sleepForTimeInterval:2];
            NSLog(@"Two");
            
        });
        //dispatch_group_notify  只有当组内队列结束后才执行
        dispatch_group_notify(group, queue, ^{
           
            NSLog(@"Three");
            
        });
        
    
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
    
    
    }
    
    @end
  • 相关阅读:
    JavaScript 对象
    Java条件语句
    函数的使用注意事项:
    函数的特点
    函数的格式
    for循环
    break和continue的区别和作用
    注意事项
    CSS浮动清除的方法
    转:Oracle 中union的用法
  • 原文地址:https://www.cnblogs.com/xubaoaichiyu/p/5281030.html
Copyright © 2020-2023  润新知