美文网首页Objective-CSpiritRealm
GCD的介绍和基本使用

GCD的介绍和基本使用

作者: 你说明哥我说哎 | 来源:发表于2017-08-12 14:58 被阅读7次

GCD的介绍

GCD(Grand Central Dispatch)中文名称为“中央调度”或“大中央派发”等,是一个多核编程的解决方法。主要用于优化应用程序支持多核处理器以及其他对称多处理系统。是一个在线程池模式的基础上执行的并行任务。
在iOS开发中, 类似于GCD还有NSThread, NSOperation & NSOperationQueue等。


GCD优点

  • GCD会自动利用更多的CPU内核;
  • GCD可以用在多核并行运算;
  • GCD会自动管理线程的生命周期, 比如创建线程, 调度任务, 销毁线程等操作。

GCD的任务和队列

任务

任务是指放在GCD里的操作, 一般是用Block方式进行。
执行任务的操作有两种, 同步执行和异步执行, 两个的区别就是在是否开启新线程进行操作。

同步执行(sync) : 不会开启新线程, 只会在当前线程进行操作。
异步执行(async): 可以另外开启一个新的线程执行任务。

队列

队列指的是任务队列, 用来存放任务的队列。采用的是先进先出(FIFO)原则。
这里的队列分为两种, 并行队列和串行队列.

并行队列(Concurrent Dispatch Queue): 可以让多个任务同时执行, 如果用到并行队列的话, 是会自动开启多个线程同时执行任务。
串行队列(Serial Dispatch Queue): 任务一个接一个的执行, 完成了前面的任务再执行后面的任务。

注意: 并行队列只有在异步执行(dispatch_async)才有效。


GCD的使用

1.创建队列

可以使用dispatch_queue_create来创建对象
dispatch_queue_create(const char * _Nullable label, dispatch_queue_attr_t _Nullable attr)
第一个参数: 队列的唯一标识符,表现形式可以是字符串如:“Queue”;
第二个参数: 队列的类型, 串行队列(DISPATCH_QUEUE_SERIAL)或 并行队列(DISPATCH_QUEUE_CONCURRENT)

// 创建串行队列
dispatch_queue_t queue= dispatch_queue_create("Queue", DISPATCH_QUEUE_SERIAL);
// 创建并行队列
dispatch_queue_t queue= dispatch_queue_create("Queue", DISPATCH_QUEUE_CONCURRENT);

常用的,并行队列可以用全局并行队列dispatch_get_global_queue(long identifier, unsigned long flags)创建。
第一个参数: 队列的优先级, 一般都是用DISPATCH_QUEUE_PRIORITY_DEFAULT.
第二个参数: 一般都是用0.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

2.创建任务
// 创建同步执行任务
dispatch_sync(queue, ^{
    // service code
});
// 创建异步执行任务
dispatch_async(queue, ^{
    // service code
});

队列和任务的组合:

同步执行(sync) 异步执行(async)
并行队列 不开启新线程, 串行方式执行任务 开启新线程, 并行方式执行任务
串行队列 不开启新线程, 串行方式执行任务 开启一条新线程, 串行方式执行任务
主队列 不开启新线程, 串行方式执行任务 不开启新线程, 串行方式执行任务

CGD的基本使用

  • 并行队列同步执行
- (void)dispatch_sync_queue_concurrent {
    NSLog(@"Start working on a task");
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{
        NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
    });
    NSLog(@"Finish working on a task");
}
2017-08-12 14:34:57.299 GCDTest[1974:149023] Start working on a task
2017-08-12 14:34:57.299 GCDTest[1974:149023] The first task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:34:57.299 GCDTest[1974:149023] The second task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:34:57.300 GCDTest[1974:149023] The third task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:34:57.300 GCDTest[1974:149023] Finish working on a task
  • 当前的线程都为同一条(main线程),而且线程数只有1;
  • 从执行顺序上, 并行队列同步执行是一个任务一个任务的去执行的。

  • 并行队列异步执行
- (void)dispatch_async_queue_concurrent {
    NSLog(@"Start working on a task");
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
    });
    NSLog(@"Finish working on a task");
}
2017-08-12 14:35:33.395 GCDTest[1974:149023] Start working on a task
2017-08-12 14:35:33.396 GCDTest[1974:149023] Finish working on a task
2017-08-12 14:35:33.396 GCDTest[1974:149163] The first task of the current thread:<NSThread: 0x6000002702c0>{number = 3, name = (null)}
2017-08-12 14:35:33.396 GCDTest[1974:149997] The second task of the current thread:<NSThread: 0x6000002705c0>{number = 4, name = (null)}
2017-08-12 14:35:33.396 GCDTest[1974:149998] The third task of the current thread:<NSThread: 0x608000265c40>{number = 5, name = (null)}
  • 当前的线程数有多条, 而且线程的名字未知;
  • 从时间上来看, 几乎都是在同一时间执行任务的;
  • 并行队列异步执行的组合除了在主队列上执行, 还会另外开启多几条线程来并行执行任务。

  • 串行队列同步执行
- (void)dispatch_sync_queue_serial {
    NSLog(@"Start working on a task");
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
    });
    NSLog(@"Finish working on a task");
}
2017-08-12 14:36:08.965 GCDTest[1974:149023] Start working on a task
2017-08-12 14:36:08.966 GCDTest[1974:149023] The first task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:36:08.966 GCDTest[1974:149023] The second task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:36:08.966 GCDTest[1974:149023] The third task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:36:08.966 GCDTest[1974:149023] Finish working on a task
  • 从执行顺序上,串行队列同步执行是一个任务一个任务的去执行的。

  • 串行队列异步执行
- (void)dispatch_async_queue_serial {
    NSLog(@"Start working on a task");
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
    });
    NSLog(@"Finish working on a task");
}
2017-08-12 14:36:22.973 GCDTest[1974:149023] Start working on a task
2017-08-12 14:36:22.973 GCDTest[1974:149023] Finish working on a task
2017-08-12 14:36:22.974 GCDTest[1974:149163] The first task of the current thread:<NSThread: 0x6000002702c0>{number = 3, name = (null)}
2017-08-12 14:36:22.974 GCDTest[1974:149163] The second task of the current thread:<NSThread: 0x6000002702c0>{number = 3, name = (null)}
2017-08-12 14:36:22.974 GCDTest[1974:149163] The third task of the current thread:<NSThread: 0x6000002702c0>{number = 3, name = (null)}
  • 开启新线程来执行任务,由于是串行队列,所以任务还是一个接着一个来执行。
  • 任务并不是一下子就开始执行的,是需要将任务都添加到队列里,然后才开始同步执行。

  • 主队列同步执行
- (void)dispatch_sync_queue_main {
    NSLog(@"Start working on a task");
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
    });
    NSLog(@"Finish working on a task");
}
2017-08-12 14:36:43.542 GCDTest[1974:149023] Start working on a task
  • 所有放在主队列里执行的任务都会放到主线程里执行;

运行的时候出现异常, 系统崩溃~~~
同步执行是一个一个任务去执行的,当主线程还在执行 [self dispatch_sync_queue_main] 的时候,往主线程里添加任务,这个时候就会出现异常现象,我们称之为卡线程


  • 主队列异步执行
- (void)dispatch_async_queue_main {
    NSLog(@"Start working on a task");
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
    });
    NSLog(@"Finish working on a task");
}
2017-08-12 14:37:08.303 GCDTest[2047:151940] Start working on a task
2017-08-12 14:37:08.303 GCDTest[2047:151940] Finish working on a task
2017-08-12 14:37:08.304 GCDTest[2047:151940] The first task of the current thread:<NSThread: 0x608000067d00>{number = 1, name = main}
2017-08-12 14:37:08.305 GCDTest[2047:151940] The second task of the current thread:<NSThread: 0x608000067d00>{number = 1, name = main}
2017-08-12 14:37:08.305 GCDTest[2047:151940] The third task of the current thread:<NSThread: 0x608000067d00>{number = 1, name = main}
  • 所有放在主队列里执行的任务都会放到主线程里执行。
  • 虽然用的是异步执行,具备了开启新线程的能力,但是由于这是主队列,所以所有的任务都是在主线程中,任务也是一个接着一个顺序执行。
  • 任务并不是马上就执行的,而是把所有任务都添加到队列里之后再执行。

相关文章

  • 多线程之GCD

    GCD介绍 1、GCD简介 2、GCD任务和队列 3、GCD 的基本使用 4、GCD 线程间的通信 5、GCD 的...

  • GCD的介绍和基本使用

    GCD的介绍 GCD(Grand Central Dispatch)中文名称为“中央调度”或“大中央派发”等,是一...

  • iOS GCD基本介绍和使用

    1.GCD简介 OverviewGrand Central Dispatch (GCD) comprises la...

  • iOS-多线程:GCD

    GCD 简介 GCD 任务和队列 GCD 的使用步骤 GCD 的基本使用(6种不同组合区别) GCD 线程间的通信...

  • 多线程基础02-GCD

    阅读原文--关注我的博客 了解完多线基础概念和NSTread的基本使用后,本文介绍GCD的主要用方法 GCD全称 ...

  • [iOS笔记]GCD介绍和基本使用

    GCD是什么 全称是 Grand Central Dispatch 是纯C语言,提供了非常多强大的函数 是 lib...

  • iOS基础:多线程-深入理解GCD

    前言 本篇文章不会介绍GCD的底层实现!!!本篇文章不会介绍GCD的基本使用!!!本篇文章是我这两天再次理解GCD...

  • 多线程和AFN网络框架配合使用

    ios的多线程一般有NSOperation和GCD.NSOperation基本使用: GCD基本使用: 简单的多线...

  • iOS多线程--彻底学会多线程之『GCD』

    GCD 文章目录 GCD简介 任务和队列 GCD的使用步骤 队列的创建方法 任务的创建方法 GCD的基本使用 并行...

  • iOS GCD

    GCD 简介 GCD 任务和队列 GCD 的使用步骤 GCD 的基本使用(六种组合不同区别,队列嵌套情况区别,相互...

网友评论

    本文标题:GCD的介绍和基本使用

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