• 多线程简介及GCD的使用


    多线程简介:       

    对于任意一个iOS应用,程序运行起来后,默认会产生一个主线程(MainThread),主线程专门用来处理UIKit对象的操作,如界面的显示与更新、处理用户事件触发的操作等等。(记忆这点,所有与UI相关的操作都要在主线程中进行)

    对于一个App应用来说,之所以需要引入多个线程,很大程度上是由于有一些操作是非常耗时的,例如:发送网络请求并等待服务器的响应,这种耗时操作是不能 够放在主线程中进行操作的,因为在等待的时间内,主线程被使用,用户是不能做任何交互动作的,因而会极大影响用户体验。对于耗时的操作,需要再另外创建一 个线程,放到后台处理,当处理完成得到结果后,再返回主线程去设置UI界面,这就涉及到线程间通信的相关知识。

    那什么是GCD呢?

    GCD(Grand Central Dispatch)技术,苹果首先应用于OSX中,随后在iOS中也引入了GCD技术。特别是苹果手机把CPU升级为多核后,GCD的使用变得更加广泛和 重要。相比于NSThread, GCD中已经完全屏蔽了有关线程的概念,而是引入了任务和队列,把任务放到队列中执行,制定任务和队列的类型,有关线程管理的事务完全交由GCD来处理, 大大简化了多任务开发的难度。在GCD中,程序员已经不再需要去关心有关线程的操作(如:线程创建、线程销毁、线程调度),而是引入了任务和队列两个核心概念。

    由于GCD对线程管理进行了封装,因此,当工程师使用GCD时,只需要把任务(通常封装在一个block中)添加到一个队列中执行,有关线程调度的工作,完全交由GCD完成。

    在使用GCD处理多任务执行时,只要按照如下步骤执行即可,

    • 在block中定义需要执行的任务内容;
    • 把任务添加到队列queue中

    GCD对队列中的任务,按照“先进先出”的原则,根据任务添加到队列的顺序来对队列进行处理,GCD会根据任务和队列的类型,自动在多个线程之间分配工作。

    GCD中,队列是一个重要概念。系统提供了若干预定义的队列,其中包括可以获取应用程序的主队列(任务始终在主线程上执行,UI操作需要在主队列中完成)。

    GCD队列严格按照“先进先出”的原则,添加到GCD队列中的任务,始终会按照加入队列的顺序被执行。

    GCD中最常见的是串行队列和并行队列:

    1. 并行队列:并行队列中的任务可以在多个线程之间分配执行,分配的原则由GCD控制,因此,并行队列中的任务,虽然分配执行时按照先进先出进行分配的,但由于各个任务被分配到不同的线程执行,因此其完成时间有可能不同,即:后分配的任务有可能先执行完成;并发队列一定需要和异步执行的任务(使用 dispatch_async())结合起来使用才有意义。
    2. 串行队列:串行队列中的任务是按照顺序一个一个完成的,当一个任务完成后,才去执行下一个任务;因此,串行队列对应一个线程执行。
    3. 主队列:主队列也是一个串行队列,主队列中的任务都在主线程中执行。

    接下来用代码来清晰的展示GCD的功能.

     1     //CGD以队列的形式进行操作的,特点:"先进先出"
     2 #pragma mark - 使用GCD去创建一个串行队列
     3     //第一种:系统提供的创建串行队列的方法(主线程main)
     4     dispatch_queue_t queue = dispatch_get_main_queue();
     5     //真正的开发中如果需要创建串行队列,比较习惯用这种
     6     //第二种:自己去创建(串行队列:SERIAL)
     7     //参数一:是系统提供的一个宏
     8     //参数二:是系统的保留字段
     9     //两个参数的位置没有严格的限定,只要写这个两个参数即可
    10     dispatch_queue_t queue = dispatch_queue_create(DISPATCH_QUEUE_SERIAL, 0);
    11     
    12 #pragma mark - 使用GCD创建并行队列
    13 //第一种方式(全局并行队列)
    14     //参数一:优先级(有四个,没有明显的区别)
    15     //参数二:系统保留字段
    16     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    17     //第二种方式:自己创建的
    18     //参数一:表示你这个队列的一个名字
    19     //参数二:系统提供的宏
    20     dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    21     //有队列的,是根据队列去创建子线程,是没有固定顺序的,随机执行,下面创建5个子线程添加到并行队列中,运行可以看出,执行是没有固定顺序的.
    22     dispatch_async(queue, ^{
    23         NSLog(@"111%@, 111%@", [NSThread currentThread], [NSThread mainThread]);
    24     });
    25     
    26     dispatch_async(queue, ^{
    27         NSLog(@"222%@, 222%@", [NSThread currentThread], [NSThread mainThread]);
    28     });
    29     
    30     dispatch_async(queue, ^{
    31         NSLog(@"333%@, 333%@", [NSThread currentThread], [NSThread mainThread]);
    32     });
    33     
    34     dispatch_async(queue, ^{
    35         NSLog(@"444%@, 444%@", [NSThread currentThread], [NSThread mainThread]);
    36     });
    37     
    38     dispatch_async(queue, ^{
    39         NSLog(@"555%@, 555%@", [NSThread currentThread], [NSThread mainThread]);
    40     });
    41     
    42 #pragma mark - 几秒之后去做每一件事
    43     //延时队列
    44     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    45         NSLog(@"3.0秒之后");
    46     });
    47 
    48 #pragma mark - 重复往一个队列中添加多个任务
    49     //还是创建一个并行队列(CONCURRENT:并行,与最上面介绍的串行相对应)
    50     dispatch_queue_t queue = dispatch_queue_create(0, DISPATCH_QUEUE_CONCURRENT);
    51     //添加多个任务
    52     //参数一:任务的数量(重复执行100次)
    53     //参数二:队列名,可以随便起个名,这里我就起名index
    54     dispatch_apply(100, queue, ^(size_t index) {
    55         NSLog(@"%ld", index);
    56     });
    57     
    58 #pragma mark - 分组group
    59     //创建一个分组(为了是安插监听函数)
    60     dispatch_group_t group = dispatch_group_create();
    61     //创建一个并行队列
    62     dispatch_queue_t queue = dispatch_queue_create(0, DISPATCH_QUEUE_CONCURRENT);
    63     //创建任务一
    64     dispatch_group_async(group, queue, ^{
    65         NSLog(@"我是任务一");
    66     });
    67     dispatch_group_async(group, queue, ^{
    68         NSLog(@"我是任务二");
    69     });
    70     
    71     //任务监管的函数,监听所有执行任务的执行情况的,必须放在所有任务的最下方
    72     dispatch_group_notify(group, queue, ^{
    73         NSLog(@"我是监考官");
    74     });
    GCD串行,并行
  • 相关阅读:
    Remove Element
    C++ 一些STL
    Two Pointers/hash/3Sum/4Sum类题目
    动态规划
    UVa 12657 双向链表
    并行运行环境
    多线程编程
    HTML XML CSS JS 迅速学习
    UVa 11988 数组模拟链表
    静态链表
  • 原文地址:https://www.cnblogs.com/lovebugssun/p/5503086.html
Copyright © 2020-2023  润新知