iOS三种多线程编程技术:

1.NSThread

2.NSOperation
3.GCD(Grand Central Dispatch)
从上到下,抽象度层次从低到高,抽象度越高的使用越简单,也是Apple最推荐使用的
 
1.NSThread 需要自己管理线程的生命周期、线程同步。线程同步对数据的加锁会有一定的系统开销(他比其他两个轻量级)
2.NSOperation 不需要关心线程管理,数据同步的事,可以把精力放在自己需要执行的操作上

GCD概念简单理解

GCD是基于C的Api。不需要自己管理线程生死。只需要创建队列,把任务放进队列里面就可以了。看上去很简单,其实也是有一段心酸路。

 

GCD有两个核心概念。一个是任务,一个是队列。

同步函数:在当前线程中执行,不开启新的线程

 

dispatch_sync(dispatch_queue_t queue, dispatch_block_tblock);

异步函数:具备开启线程的能力。

 

dispatch_async(dispatch_queue_t queue, dispatch_block_tblock);

队列

并发队列

 

自动开启多个线程,并且可以让多个任务同时执行。

 

仅仅在异步函数(dispatch_async)下有效。

串行队列

 

让线程一个接着一个的执行。一条线程执行完后再执行下一条线程。

并发队列

并发队列不需要手动创建。以下是创建代码。

dispatch_queue_tdispatch_get_global_queue(
dispatch_queue_priority_tpriority,// 队列的优先级
unsignedlongflags);// 此参数暂时无用,用0即可
dispatch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//获得全局并发队列 全局并发队列的优先级
#defineDISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#defineDISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)
#defineDISPATCH_QUEUE_PRIORITY_LOW (-2)// 低
#defineDISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台
串行队列
使用dispatch_queue_create函数创建串行队列
dispatch_queue_t
dispatch_queue_create(constchar*label, //队列名称
dispatch_queue_attr_tattr);//队列属性,一般用NULL即可
dispatch_queue_tqueue = dispatch_queue_create("isQueue", NULL);//创建
dispatch_release(queue);//非ARC时候需要释放手动创建的队列 使用主队列(跟主线程相关联的队列)
主队列是GCD自带的一种特殊的串行队列
放在主队列中的任务,都会放到主线程中执行
使用dispatch_get_main_queue()获得主队列
dispatch_queue_tqueue = dispatch_get_main_queue();

使用dispatch_sync同步函数时候,在主线程中往主队列添加任务会造成死锁

队列与任务的结合
函数 全局并发队列 手动创建串行队列 主队列
同步 (sync) 没有开启新线程 串行执行任务 没有开启新线程 串行执行任务 没有开启新线程 串行执行任务
异步 (async) 有开启新线程 并发执行任务 有开启新线程 串行执行任务 没有开启新线程 串行执行任务
线程间的通讯

更新UI,数据等都是要回到主线程的。不能在子线程。

//获取全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{ NSLog(@"-子线程-- 开始下载图片--%@",[NSThread currentThread]); //下载数据是耗时操作放到子线程
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/b219ebc4b74543a94369f4cb1c178a82b9011442.jpg"]]]; dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"-主线程-- 刷新UI--%@",[NSThread currentThread]);
//回到主线程刷新UI
self.imageView.image = image;
});
});
延时操作

延时操作不会堵塞当前线程.

//延迟操作
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)),//从什么时候开始,是一个固定的算法
dispatch_get_main_queue(),//队列
^{
//做要做的操作
});
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #pragma mark 延迟操作创建一
//获取全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //延时多久
dispatch_time_t whenTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)); //延时操作,根据whenTime设计的时间
dispatch_after(whenTime, queue, ^{
NSLog(@"倒计时结束"); dispatch_async(queue, ^{
NSLog(@"-子线程-- 开始下载图片--%@",[NSThread currentThread]); //下载数据是耗时操作放到子线程
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/b219ebc4b74543a94369f4cb1c178a82b9011442.jpg"]]]; dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"-主线程-- 刷新UI--%@",[NSThread currentThread]); //回到主线程刷新UI
self.imageView.image = image; });
});
});
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #pragma mark 延迟操作创建二
//获取全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"倒计时结束"); dispatch_async(queue, ^{
NSLog(@"-子线程-- 开始下载图片--%@",[NSThread currentThread]); //下载数据是耗时操作放到子线程
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/b219ebc4b74543a94369f4cb1c178a82b9011442.jpg"]]]; dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"-主线程-- 刷新UI--%@",[NSThread currentThread]); //回到主线程刷新UI
self.imageView.image = image;
});
});
});
GCD一次性代码
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//代码只执行一次
});
});
GCD队列组
分组模式 dispatch_group_notify

可以异步执行多个耗时操作。等耗时操作都执行完毕之后会回到主线程执行操作。主要用于监听任务是否完成。

//获取全局队列
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//创建一个队列组
dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, globalQueue, ^{ NSLog(@"--- 1 开始--- %@",[NSThread currentThread]);
//延时5秒 模仿堵塞子线程
[NSThread sleepForTimeInterval:5];
NSLog(@"--- 2 --- 完成 %@",[NSThread currentThread]); }); dispatch_group_async(group, globalQueue, ^{ NSLog(@"--- 2 开始--- %@",[NSThread currentThread]);
//延时5秒 模仿堵塞子线程
[NSThread sleepForTimeInterval:5];
NSLog(@"--- 2 --- 完成 %@",[NSThread currentThread]); }); //在这个队列组里面,会等group中的全部代码执行完毕再去执行其它的操作
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 等前面的异步操作都执行完毕后,回到主线程...
NSLog(@"全部完成"); }); //非ARC时候要释放掉
//dispatch_release(group);
dispatch_apply组内无序循环执行任务
//循环执行任务,并且执行任务的顺序是无序列的。这里会堵塞当前的线程。所以要注意。一般都是在子线程中执行。
dispatch_apply(size_t iterations,//执行的次数
<#dispatch_queue_t queue#>,//队列
<#^(size_t)block#>)//任务
dispatch_apply(5, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
NSLog(@"%zu",index);
});
dispatch_set_target_queue 变更queue的优先级别
dispatch_queue_t exampleQueue = dispatch_queue_create("com.example.queue", NULL);     //设置这个全局并发队列的优先级为后台     dispatch_queue_t globalQueued = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);     dispatch_set_target_queue(exampleQueue, globalQueued);     /**      *  经过转换之后exampleQueue的优先级别变成后台      */

GCD基础知识总结的更多相关文章

  1. GCD基础知识

    并行和并发 在英文世界里,「并行」和「并发」的区别比较清晰,「并行」对应parallelism,「并发」对应concurrency:但在中文世界里二者仅一字之差,两个概念非常容易弄混淆: 各种资料对「 ...

  2. Java基础知识【下】( 转载)

    http://blog.csdn.net/silentbalanceyh/article/details/4608360 (最终还是决定重新写一份Java基础相关的内容,原来因为在写这一个章节的时候没 ...

  3. ReactiveCocoa基础知识内容

    本文记录一些关于学习ReactiveCocoa基础知识内容,对于ReactiveCocoa相关的概念如果不了解可以网上搜索:RACSignal有很多方法可以来订阅不同的事件类型,ReactiveCoc ...

  4. Runloop基础知识

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  5. Swift之基础知识

    Swift之基础知识 出于对Swift3.0的学习,写下这篇基本语法的笔记.希望能帮助记忆 -0- 这边提供Swift3.0中文教材,资源链接: https://pan.baidu.com/s/1c2 ...

  6. iOS 开发之 GCD 基础

    header{font-size:1em;padding-top:1.5em;padding-bottom:1.5em} .markdown-body{overflow:hidden} .markdo ...

  7. 活到老学到老:iOS开发中的基础知识(一)

    本文参考 标哥的博客:宝库iOS开发笔试题 进行学习整理.与其说是看面试题,不如说是对自己知识的巩固.工欲善其事必先利其器,基础知识不牢固可能会导致编程中的一些注意不到的问题.总之一句话:活到老,学到 ...

  8. .NET面试题系列[1] - .NET框架基础知识(1)

    很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...

  9. RabbitMQ基础知识

    RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...

随机推荐

  1. 一图看懂host_only nat bridge拓扑结构

    VMware三种模式 我们在使用VMware时经常能看到三种网络的连接模式:Bridged  Host-Only Nat,它们都有什么作用,网络拓扑是怎样的?怎样才能让他们上网,他们相互间能不能相互访 ...

  2. JavaScript基础插曲—获取标签,插入元素,操作样式

    Js基础 1:document.write() 这个是动态创建元素内容,利用js.这个可以利用js来创建元素,文本,标签等,document.write()与document.writeln()的区别 ...

  3. Mac下JDK安装配置

    首先可以通过官网下载JDK:http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html,至于下什么版本根 ...

  4. WebView输入框提示

    做基于WebView应用时,页面上有一个输入框,当输入的文字过多时,超过输入框的行数时,输入框能够滚动,这时间问题来了,输入的提示箭头会移动到输入框外,如何解决这个问题呢,查找chromium源码如下 ...

  5. webservice入门(2)开发ws程序

    因为webservice分为服务端和客户端,所以如果要学习的话,那么肯定是包括这两部分的了. 1.开发服务端的webservice: 使用jdk开发ws其实很简单,只是需要一些注解:最重要的是 @We ...

  6. 优化JavaScripe 提升首页加载速度的几种方案解析

    优化目的: 1. 减少load量. 2. 优化js,加快页面加载速度. 网站中最影响网站打开速度的是什么?我会告诉是网站中的javascript,简称JS.模板中引用的JS文件越多,打开速度越慢,细读 ...

  7. Spark集群 + Akka + Kafka + Scala 开发(2) : 开发一个Spark应用

    前言 在Spark集群 + Akka + Kafka + Scala 开发(1) : 配置开发环境,我们已经部署好了一个Spark的开发环境. 本文的目标是写一个Spark应用,并可以在集群中测试. ...

  8. python处理ha文件

    ha.txt文件内容: frontend oldboy.org bind 0.0.0.0:80 option httplog option httpclose option forwardfor lo ...

  9. Linux更改主机名-适用于abuntu

    今天复制了个ubuntu虚拟机,于是想更改下主机名以作区别.这是搜到的比较完整的资料,适用abuntu,不过其他linux系统还有待求证. 1.查看主机名 在Ubuntu系统中,快速查看主机名有多种方 ...

  10. C# AOP框架入门

    AOP面向切面编程(Aspect Oriented Programming),是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.Spring框架用的核心技术就是AOP,是函数式编程的一 ...