• iOS开发之多线程 GCD


    基础知识:

    下午9:09

    一、基础概念

    1、什么是GCD

    全称是Grand Central Dispath 纯C语言编写,提供非常多且强大的函数,是目前推荐的多线程开发方法,NSOperation便是基于GCD的封装

    2、GCD的优势

        1.为多核的并行运算提出了解决方案

        2.GCD会自动利用更多的CPU内核,比如 双核,四核

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

        4.程序员只需告诉GCD想要执行什么任务,不需要编写任何线程管理代码

     3、GCD中的两个核心概念

        1.任务:执行什么操作

        2.队列:用来存放任务

     4、队列可分为两大类型

        (1)串行队列(Serial Dispatch Queue): 只能有一个线程,加入到队列中的操作按添加顺序依次执行,一个任务执行完毕后 才能执行下一个任务

        (2)并发队列(Concurrent Dispatch Queue): 可以有多个线程,操作进来之后他会将这些线程安排在可用的处理器上,同时保证先进来的任务优先处理

         (3)还有一个特殊的队列就是主队列,主队列中永远只有一个线程-主线程,用来执行主线程的操作任务

     5、采用GCD做多线程,可抽象为两步

         1、找到队列

         2、在队列中用同步或者异步的方式执行任务

     6.执行队列中任务的两种方式

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

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

     7、GCD创建的线程任务有四种方式

    二、串行同步  串行异步  并行同步  并行异步的使用

    #pragma mark-----串行同步
        dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
        dispatch_sync(serialQueue, ^{
    //        NSLog(@"%@",[NSThread currentThread]);
        });
    #pragma mark-----串行异步
        dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);
        dispatch_async(serialQueue1, ^{
    //        NSLog(@"%@",[NSThread currentThread]);
        });
    #pragma mark----并行同步
        dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_sync(concurrentQueue, ^{
    //        NSLog(@"%@",[NSThread currentThread]);
        });
    #pragma mark----并行异步
        dispatch_queue_t concurrentQueue1 = dispatch_queue_create("concurrentQueue1", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(concurrentQueue1, ^{
            NSLog(@"%@",[NSThread currentThread]);
        });

    三、具体实例 使用GCD加载多张图片

    #define kurl @"http://store.storeimages.cdn-apple.com/8748/as-images.apple.com/is/image/AppleInc/aos/published/images/s/38/s38ga/rdgd/s38ga-rdgd-sel-201601?wid=848&hei=848&fmt=jpeg&qlt=80&op_sharpen=0&resMode=bicub&op_usm=0.5,0.5,0,0&iccEmbed=0&layer=comp&.v=1454777389943"
    @interface MoreImageViewViewController ()
    {
        int imageTag;
        UIImageView *myImageView;
        dispatch_queue_t concurentQueue;
        
        NSOperationQueue *operationQueues;
    }
    
    @end
    
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        imageTag = 100;
        self.view.backgroundColor = [UIColor greenColor];
        self.edgesForExtendedLayout = UIRectEdgeNone;
        [self controlBtn];
        /*
         1、创建多个视图
         2、找到并行队列
         3、给这个并行队列指定多个任务
         4、在子线程加载网络资源
         5、回到主线程
         6、更新UI
         */
    //    1、创建多个视图
        for (int i=0; i<3; i++) {
            for (int j=0; j<2; j++) {
                myImageView = [[UIImageView alloc]initWithFrame:CGRectMake(10+j*200, 40+i*200, 190, 190)];
                myImageView.backgroundColor = [UIColor orangeColor];
                myImageView.tag = imageTag++;
                [self.view addSubview:myImageView];
            }
        }
    // 2、找到并行队列
    //    使用下面这个方式不按顺序  因为下面这句找的是  系统的全局并行队列
    //    concurentQueue = dispatch_get_global_queue(0, 0);
    //    这个方式是按顺序的  用的串行队列
        concurentQueue = dispatch_queue_create("concurentQueue", DISPATCH_QUEUE_SERIAL);
        
    //    3、指定任务
        for (int index=0; index<6; index++) {
            dispatch_async(concurentQueue, ^{
               [NSThread sleepForTimeInterval:1];
    //            加载网络资源
                NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kurl]];
                UIImage *image = [UIImage imageWithData:data];
                
    //            5、回到主线程
                dispatch_queue_t mainQueue = dispatch_get_main_queue();
                dispatch_sync(mainQueue, ^{
                   
    //                6、刷新UI
                    for (int i=0; i<6; i++) {
                        UIImageView *iamgeView = [self.view viewWithTag:100+index];
                        iamgeView.image = image;
                    }
                    
                });
            });
        }
        
        
        
    
    }
    
    
    以下两个方法是暂停和开启线程的
    - (void)controlBtn{
        
        
        UISegmentedControl *segment = [[UISegmentedControl alloc]initWithItems:@[@"暂停",@"开启",]];
        
        segment.frame = CGRectMake(50, 620, 300, 50);
        
        segment.apportionsSegmentWidthsByContent = YES;
        
        [self.view addSubview:segment];
        
        [segment addTarget:self action:@selector(clickSegment:) forControlEvents:UIControlEventValueChanged];
    }
    
    - (void)clickSegment:(UISegmentedControl *)sender {
        
        switch (sender.selectedSegmentIndex) {
                
            case 0:{
                //            暂停队列
                dispatch_suspend(concurentQueue);
            }break;
                
            case 1:{
                //            恢复队列
                dispatch_resume(concurentQueue);
                
            }break;
                
        }
        
        
        
    }
  • 相关阅读:
    [NOIp pj 2007][Luogu P1095] 守望者的逃离
    [Noip 2009 普及组 T4] [Luogu P1070] 道路游戏
    跟风Manacher算法整理
    Luogu P2569 [SCOI2010] 股票交易
    qbzt2020五一DAY1T1集合——题解
    Cena使用教程
    2020.4.15校内测试
    康托展开学习笔记
    qbzt网格图路径问题——题解
    2-sat基础详解
  • 原文地址:https://www.cnblogs.com/ios-wanglong/p/5297418.html
Copyright © 2020-2023  润新知