多线程 -- GCD
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_sync
队列
- 并发队列
- 可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
- 并发功能只有在异步(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_once函数能保证某段代码在
- 快速迭代
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的更多相关文章
- iOS 多线程GCD的基本使用
<iOS多线程简介>中提到:GCD中有2个核心概念:1.任务(执行什么操作)2.队列(用来存放任务) 那么多线程GCD的基本使用有哪些呢? 可以分以下多种情况: 1.异步函数 + 并发队列 ...
- iOS多线程 GCD
iOS多线程 GCD Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法. dispatch queue分成以下三种: 1)运行在主线程的Main que ...
- 修改版: 小伙,多线程(GCD)看我就够了,骗你没好处!
多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能.具有这种能力的系 ...
- ios多线程-GCD基本用法
ios中多线程有三种,NSTread, NSOperation,GCD 这篇就讲讲GCD的基本用法 平时比较多使用和看到的是: dispatch_async(dispatch_get_global_q ...
- iOS 多线程GCD简介
一.简介 1.1 GCD (Grand Central Dispatch )是Apple开发的一个多核编程的解决方法. Grand 含义是“伟大的.宏大的”,Central含义“中央的”,Dispat ...
- 多线程GCD的基本使用以及注意点
GCD的使用 一:队列 1.串行队列:添加到队列中的任务是一个一个执行的 2.并行(发)队列:添加到队列中的任务是多个同时执行的(一个队列中的多个任务可以同时执行) 3.主队列:里 ...
- IOS开发之多线程 -- GCD的方方面面
前言:这篇GCD的博文是本人阅读了很多海内外大神的关于GCD的文章,以及结合之前自己对GCD的粗浅的认识,然后取其精华,去其槽粕,综合起来的笔记,而且是尽可能的以通熟易懂的并且是正确的理论论述方式呈现 ...
- 刀哥多线程GCD核心概念gcd
GCD GCD 核心概念 将任务添加到队列,并且指定执行任务的函数 任务使用 block 封装 任务的 block 没有参数也没有返回值 执行任务的函数 异步 dispatch_async 不用等待当 ...
- ios开发多线程--GCD
引言 虽然GCD使用很广,而且在面试时也经常问与GCD相关的问题,但是我相信深入理解关于GCD知识的人肯定不多,大部分都是人云亦云,只是使用过GCD完成一些很简单的功能.当然,使用GCD完成一些简单的 ...
- 多线程GCD
经常使用:规避很多线程相关的复杂的逻辑 为什么会gcd?因为pthread和nsthread要求开发人员对线程相关的知识了解深入; 手动启动线程:加锁/解锁;造成很多隐患 --> 苹果公司给出了 ...
随机推荐
- leetcode 6
题目描述: 该开始就输在了理解题意上.. 没搞懂zigzag是什么意思. 查了一些解释终于明白要干什么了. 将一个字符串按照Z字形排列(侧着看):再把结果按行输出. 刚开始的想法是讲字符串按照 ...
- PowerDesigner生成Oracle数据字典
PowerDesigner版本信息 1.File-->NewModel... 2.选择模型 New Model Model types-->Physical Data Model --&g ...
- Unieap3.5-需要用到window.setTimeout的地方
1.js大数据量操作且需要显示进度条 unieap.showLoading(true);//进度条 window.setTimeout(function(){ checkUtils.setAllRow ...
- sqlserver分区表实践:对时间分区表自动进行管理
项目问题:有一张日志表,插入和查询为主,每天记录数据为200多万,大小为2G-4G之间.一开始开发人员使用delete语句手动删除,保留7天数据,经常造成阻塞和性能瓶颈.但是如果不删除数据随着表越来越 ...
- Python之路【第五篇】:面向对象及相关
Python之路[第五篇]:面向对象及相关 面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...
- 简单记事本程序java源码项目
代码如下 import java.awt.*; import java.io.*; import java.awt.datatransfer.*; import java.awt.event.*; p ...
- [leetcode]_Maximum Depth of Binary Tree
第三道树的题目,我还是不会,我擦,怎么递归算法还是不能很好理解.看来还得好好研究下递归算法. 题目:求一棵树的最大深度. 思路:递归地求取左子树最大深度 和 右子树最大深度,返回较大值即为 整棵树的 ...
- jquery 消息提醒插件 toastmessage
最近做系统,想到使用后台要使用消息提醒,但是一直苦恼消息提醒的效果,于是找了一个toastmessage,还不错.记录下使用的方法. 第一步:引入需要的文件 <script type=" ...
- Android———从GitHub上下载源码的方法【Written By KillerLegend】
首先声明,本文说的是从GitHub上下载源码而非上传源码! 1:下载tortoisegit,下载地址为: https://code.google.com/p/tortoisegit/wiki/Down ...
- IOS学习4
---恢复内容开始--- UIScrollView 屏幕展示有限,超出一个屏时用户可滚动查看过多部分.UIView不具备滚动功能. -取消autolayout -设置CGSize contentSiz ...