• GCD中有2个核心概念

    • 任务:执行什么操作
    • 队列:用来存放任务
  • 执行任务

    • 同步方法: dispatch_sync

      dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
      queue:队列
      block:任务
    • 异步方法: dispatch_async
      dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
    • 同步和异步的区别
      • 同步:只能在当前线程中执行任务,不具备开启新线程的能力
      • 异步:可以在新的线程中执行任务,具备开启新线程的能力
  • 队列

    • 并发队列

      • 可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
      • 并发功能只有在异步(dispatch_async)函数下才有效
    • 串行队列
      • 让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
  • 注意点

    • 同步和异步主要影响:能不能开启新的线程

      • 同步:只是在当前线程中执行任务,不具备开启新线程的能力
      • 异步:可以在新的线程中执行任务,具备开启新线程的能力
    • 并发和串行主要影响:任务的执行方式
      • 并发:允许多个任务并发(同时)执行
      • 串行:一个任务执行完毕后,再执行下一个任务
  • 各种任务队列搭配

    • 同步 + 串行
    • /*
      同步 + 串行: 不会开启新的线程
      注意点: 如果是调用 同步函数, 那么会等同步函数中的任务执行完毕, 才会执行后面的代码
      */
      - (void)syncSerial
      {
      // 1.创建一个串行队列
      // #define DISPATCH_QUEUE_SERIAL NULL
      // 所以可以直接传NULL
      dispatch_queue_t queue = dispatch_queue_create("com.520it.lnj", NULL); // 2.将任务添加到队列中
      dispatch_sync(queue, ^{
      NSLog(@"任务1 == %@", [NSThread currentThread]);
      });
      dispatch_sync(queue, ^{
      NSLog(@"任务2 == %@", [NSThread currentThread]);
      });
      dispatch_sync(queue, ^{
      NSLog(@"任务3 == %@", [NSThread currentThread]);
      }); NSLog(@"---------");
      }
    • 同步 + 并发 *
      /*
      同步 + 并发 : 不会开启新的线程
      妻管严
      */
      - (void)syncConCurrent
      {
      // 1.创建一个并发队列
      dispatch_queue_t queue = dispatch_get_global_queue(0, 0); // 2.将任务添加到队列中
      dispatch_sync(queue, ^{
      NSLog(@"任务1 == %@", [NSThread currentThread]);
      });
      dispatch_sync(queue, ^{
      NSLog(@"任务2 == %@", [NSThread currentThread]);
      });
      dispatch_sync(queue, ^{
      NSLog(@"任务3 == %@", [NSThread currentThread]);
      }); NSLog(@"---------");
      }
    • 异步 + 串行 *
      /*
      异步 + 串行:会开启新的线程
      但是只会开启一个新的线程
      注意: 如果调用 异步函数, 那么不用等到函数中的任务执行完毕, 就会执行后面的代码
      */
      - (void)asynSerial
      {
      // 1.创建串行队列
      dispatch_queue_t queue = dispatch_queue_create("com.520it.lnj", DISPATCH_QUEUE_SERIAL);
      /*
      能够创建新线程的原因:
      我们是使用"异步"函数调用
      只创建1个子线程的原因:
      我们的队列是串行队列
      */
      // 2.将任务添加到队列中
      dispatch_async(queue, ^{
      NSLog(@"任务1 == %@", [NSThread currentThread]);
      });
      dispatch_async(queue, ^{
      NSLog(@"任务2 == %@", [NSThread currentThread]);
      });
      dispatch_async(queue, ^{
      NSLog(@"任务3 == %@", [NSThread currentThread]);
      }); NSLog(@"--------");
      }
    • 异步 + 并发 *
      /*
      异步 + 并发 : 会开启新的线程
      如果任务比较多, 那么就会开启多个线程
      */
      - (void)asynConcurrent
      {
      /*
      执行任务
      dispatch_async
      dispatch_sync
      */ /*
      第一个参数: 队列的名称
      第二个参数: 告诉系统需要创建一个并发队列还是串行队列
      DISPATCH_QUEUE_SERIAL :串行
      DISPATCH_QUEUE_CONCURRENT 并发
      */
      // dispatch_queue_t queue = dispatch_queue_create("com.520it.lnj", DISPATCH_QUEUE_CONCURRENT); // 系统内部已经给我们提供好了一个现成的并发队列
      /*
      第一个参数: iOS8以前是优先级, iOS8以后是服务质量
      iOS8以前
      * - DISPATCH_QUEUE_PRIORITY_HIGH 高优先级 2
      * - DISPATCH_QUEUE_PRIORITY_DEFAULT: 默认的优先级 0
      * - DISPATCH_QUEUE_PRIORITY_LOW: 低优先级 -2
      * - DISPATCH_QUEUE_PRIORITY_BACKGROUND: iOS8以后
      * - QOS_CLASS_USER_INTERACTIVE 0x21 用户交互(用户迫切想执行任务)
      * - QOS_CLASS_USER_INITIATED 0x19 用户需要
      * - QOS_CLASS_DEFAULT 0x15 默认
      * - QOS_CLASS_UTILITY 0x11 工具(低优先级, 苹果推荐将耗时操作放到这种类型的队列中)
      * - QOS_CLASS_BACKGROUND 0x09 后台
      * - QOS_CLASS_UNSPECIFIED 0x00 没有设置 第二个参数: 废物
      */
      dispatch_queue_t queue = dispatch_get_global_queue(0, 0); /*
      第一个参数: 用于存放任务的队列
      第二个参数: 任务(block) GCD从队列中取出任务, 遵循FIFO原则 , 先进先出
      输出的结果和苹果所说的原则不符合的原因: CPU可能会先调度其它的线程 能够创建新线程的原因:
      我们是使用"异步"函数调用
      能够创建多个子线程的原因:
      我们的队列是并发队列
      */
      dispatch_async(queue, ^{
      NSLog(@"任务1 == %@", [NSThread currentThread]);
      });
      dispatch_async(queue, ^{
      NSLog(@"任务2 == %@", [NSThread currentThread]);
      });
      dispatch_async(queue, ^{
      NSLog(@"任务3 == %@", [NSThread currentThread]);
      });
      }
    • 异步 + 主队列 *
       异步 + 主队列 : 不会创建新的线程, 并且任务是在主线程中执行
      */
      - (void)asyncMain
      {
      // 主队列:
      // 特点: 只要将任务添加到主队列中, 那么任务"一定"会在主线程中执行 \
      无论你是调用同步函数还是异步函数
      dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{
      NSLog(@"%@", [NSThread currentThread]);
      });
      }
    • 同步 + 主队列 *
      /*
      如果是在主线程中调用同步函数 + 主队列, 那么会导致死锁
      导致死锁的原因:
      sync函数是在主线程中执行的, 并且会等待block执行完毕. 先调用
      block是添加到主队列的, 也需要在主线程中执行. 后调用
      */
      - (void)syncMain
      {
      NSLog(@"%@", [NSThread currentThread]);
      // 主队列:
      dispatch_queue_t queue = dispatch_get_main_queue(); // 如果是调用 同步函数, 那么会等同步函数中的任务执行完毕, 才会执行后面的代码
      // 注意: 如果dispatch_sync方法是在主线程中调用的, 并且传入的队列是主队列, 那么会导致死锁
      dispatch_sync(queue, ^{
      NSLog(@"----------");
      NSLog(@"%@", [NSThread currentThread]);
      });
      NSLog(@"----------");
      }
  • GCD线程间通信

dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行耗时的异步操作...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,执行UI刷新操作
});
});
  • GCD其它用法
  • 延时执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2秒后执行这里的代码...
});
  • 一次性代码

    • 使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次
    •  static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ 
      
      // 只执行1次的代码(这里面默认是线程安全的) 
      
      });

- 快速迭代

dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){
// 执行10次代码,index顺序不确定
});
  • barrier (栅栏)

    • 在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
    • 不能是全局的并发队列
    • 所有的任务都必须在一个队列中
dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
  • 队列组
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的更多相关文章

  1. iOS 多线程GCD的基本使用

    <iOS多线程简介>中提到:GCD中有2个核心概念:1.任务(执行什么操作)2.队列(用来存放任务) 那么多线程GCD的基本使用有哪些呢? 可以分以下多种情况: 1.异步函数 + 并发队列 ...

  2. iOS多线程 GCD

    iOS多线程 GCD Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法. dispatch queue分成以下三种: 1)运行在主线程的Main que ...

  3. 修改版: 小伙,多线程(GCD)看我就够了,骗你没好处!

    多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能.具有这种能力的系 ...

  4. ios多线程-GCD基本用法

    ios中多线程有三种,NSTread, NSOperation,GCD 这篇就讲讲GCD的基本用法 平时比较多使用和看到的是: dispatch_async(dispatch_get_global_q ...

  5. iOS 多线程GCD简介

    一.简介 1.1 GCD (Grand Central Dispatch )是Apple开发的一个多核编程的解决方法. Grand 含义是“伟大的.宏大的”,Central含义“中央的”,Dispat ...

  6. 多线程GCD的基本使用以及注意点

    GCD的使用  一:队列    1.串行队列:添加到队列中的任务是一个一个执行的    2.并行(发)队列:添加到队列中的任务是多个同时执行的(一个队列中的多个任务可以同时执行)    3.主队列:里 ...

  7. IOS开发之多线程 -- GCD的方方面面

    前言:这篇GCD的博文是本人阅读了很多海内外大神的关于GCD的文章,以及结合之前自己对GCD的粗浅的认识,然后取其精华,去其槽粕,综合起来的笔记,而且是尽可能的以通熟易懂的并且是正确的理论论述方式呈现 ...

  8. 刀哥多线程GCD核心概念gcd

    GCD GCD 核心概念 将任务添加到队列,并且指定执行任务的函数 任务使用 block 封装 任务的 block 没有参数也没有返回值 执行任务的函数 异步 dispatch_async 不用等待当 ...

  9. ios开发多线程--GCD

    引言 虽然GCD使用很广,而且在面试时也经常问与GCD相关的问题,但是我相信深入理解关于GCD知识的人肯定不多,大部分都是人云亦云,只是使用过GCD完成一些很简单的功能.当然,使用GCD完成一些简单的 ...

  10. 多线程GCD

    经常使用:规避很多线程相关的复杂的逻辑 为什么会gcd?因为pthread和nsthread要求开发人员对线程相关的知识了解深入; 手动启动线程:加锁/解锁;造成很多隐患 --> 苹果公司给出了 ...

随机推荐

  1. about control %CPU

    #include <stdio.h> #include <unistd.h> #include <stdlib.h> #define timesize 200000 ...

  2. 简单记事本程序java源码项目

    代码如下 import java.awt.*; import java.io.*; import java.awt.datatransfer.*; import java.awt.event.*; p ...

  3. MySQL查询昨天、今天、7天、近30天、本月、上一月数据

    文章同步发表在博主网站朗度云,传输门:http://www.wolfbe.com/detail/201608/291.html   在开发或者统计时,我们可能需要统计某个表的数据.比如:查看今天新增的 ...

  4. 搭建高性能计算环境(二)、远程登录Linux服务器

    一般操作Linux系统都是通过远程登录使用的,本节介绍几种远程登录Linux.上传下载文件的工具. 1. Secure Shell SSH 简单方便.既能使用命令行登陆也能传文件,免费. 打开SSH ...

  5. 软件工程 speedsnail 第二次冲刺3

    20150520 完成任务:划线第三天,能画出一条直黄线且与蜗牛共存: 遇到问题: 问题1 碰撞检测有缺陷 解决1 没有解决 明日任务: 实现蜗牛与线的碰撞

  6. Data Mover Script Templates

    Datamover is probably the best way to export and import data between PeopleSoft databases and the sc ...

  7. 设置trace SQL

    Select PeopleTools, Utilities, Debug, Trace SQL to access the Trace SQL page. You use this page to c ...

  8. SMTP sendMail 失败解决办法

    If you are seeing messages like this in your message log when running a process through the process ...

  9. 通过API函数来控制SQLite数据库增删改查

    person类属性有Intenger id,String name,Intenger  age,相应的构造方法和set get方法. package com.xh.tx.dao; import and ...

  10. jquery 点击页面其他地方实现隐藏菜单功能

    1.给页面文档添加一个点击事件函数,在函数内实现隐藏菜单功能. $('html').click(function(){//Hide the menus if visible});//用$(docume ...