iOS 多线程的简单理解(1) 方式 :同步 异步
最近遇到特别糟糕的面试,过程中提到多次对多线程的处理问题,并没有很好的给予答复和解决,所以在这里做个简单的备案:
期望能更加了解和熟练使用 多线程技术:
下面都是自己的总结,如果存在不对的,或者不足,请给予指正……
1. 多线程基本概念:方式 -> 同步 + 异步
1.1 同步 : 队列任务 在当前线程,按照添加先后顺序执行,不开辟新的线程;
1.1.1 同步方法 1
- (void)syncOne{
NSLog(@"**************同步1 start ***************");
NSLog(@"同步1 start %@",[NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
// 同步执行
dispatch_sync(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"同步1 %@",[NSThread currentThread]);
}
});
NSLog(@"同步1 end %@",[NSThread currentThread]);
NSLog(@"**************同步1 end ***************");
}
打印结果:::::
2017-12-19 16:56:06.537696+0800 DeadThread[6767:1309336] **************同步1 start ***************
2017-12-19 16:56:06.537841+0800 DeadThread[6767:1309336] 同步1 start <NSThread: 0x6040000789c0>{number = 1, name = main}
2017-12-19 16:56:06.537969+0800 DeadThread[6767:1309336] 同步1 <NSThread: 0x6040000789c0>{number = 1, name = main}
2017-12-19 16:56:06.538046+0800 DeadThread[6767:1309336] 同步1 <NSThread: 0x6040000789c0>{number = 1, name = main}
2017-12-19 16:56:06.538222+0800 DeadThread[6767:1309336] 同步1 <NSThread: 0x6040000789c0>{number = 1, name = main}
2017-12-19 16:56:06.538307+0800 DeadThread[6767:1309336] 同步1 end <NSThread: 0x6040000789c0>{number = 1, name = main}
2017-12-19 16:56:06.538404+0800 DeadThread[6767:1309336] **************同步1 end ***************
得到的结果::
1.创建了同步队列:dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
1.线程在主线程执行
2.线程顺序执行的
1.1.2 同步方法 2
- (void)syncTwo{
NSLog(@"**************同步2 start ***************");
NSLog(@"同步2 start %@",[NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
// 同步执行
dispatch_async(dispatch_get_global_queue(0, 0), ^{//新开一个子线程
dispatch_sync(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"同步2 %@",[NSThread currentThread]);
}
});
});
NSLog(@"同步2 end %@",[NSThread currentThread]);
NSLog(@"**************同步2 end ***************");
}
打印结果::::
2017-12-20 10:08:49.982236+0800 DeadThread[8035:1857644] **************同步2 start ***************
2017-12-20 10:08:49.982373+0800 DeadThread[8035:1857644] 同步2 start <NSThread: 0x604000075480>{number = 1, name = main}
2017-12-20 10:08:49.982478+0800 DeadThread[8035:1857644] 同步2 end <NSThread: 0x604000075480>{number = 1, name = main}
2017-12-20 10:08:49.982512+0800 DeadThread[8035:1858341] 同步2 <NSThread: 0x60400026aa40>{number = 3, name = (null)}
2017-12-20 10:08:49.982563+0800 DeadThread[8035:1857644] **************同步2 end ***************
2017-12-20 10:08:49.982584+0800 DeadThread[8035:1858341] 同步2 <NSThread: 0x60400026aa40>{number = 3, name = (null)}
2017-12-20 10:08:49.982817+0800 DeadThread[8035:1858341] 同步2 <NSThread: 0x60400026aa40>{number = 3, name = (null)}
得到的结果:::::
1.线程在新开的线程执行;
2.线程内同步代码 运行是顺序进行的
1.1.3 同步死锁
解说一个经典的死锁代码:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"开始启动");// 1
dispatch_sync(dispatch_get_main_queue(), ^{ //2
NSLog(@"同步任务"); // 3
});
NSLog(@"启动结束"); //4
}
运行结果::::
2017-12-20 10:53:10.147278+0800 DeadThread[8403:2037075] 开始启动
(lldb)
解说原因::::
前提::1. viewDidLoad 任务是在主线程执行的 2. dispatch_sync(dispatch_get_main_queue(),^{ }); 在主线程 添加了新的任务
1.项目整体代码是 顺序运行的;
2.当代码 运行到 标记 1 时, 没有发生问题,log 正常启动,打印输出;
3.当代码 运行到 标记 2 时,添加了新的同步任务,且在同一个队列中(如图)

图示::
同步任务,view did load 任务 先添加的,所以先被执行,
运行到 标记 2 时,添加新的同步任务,此时 需要执行 这个同步任务,但此时 view did load 任务 还没有执行完毕;
造成的结果:
同步任务 需要等待 view did load 任务执行完毕;
view did load 任务 需要同步任务执行 完毕;
对不起,哥们,到了这里,程序死定了,呜呜……
1.2 异步 :具备开启新线程的能理,执行时,不影响主线程的运行
1.2.1 异步方法1
- (void)asyncOne{
NSLog(@"**************异步1 start ***************");
NSLog(@"异步1 start %@",[NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
// 异步执行
dispatch_async(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"异步1 %@",[NSThread currentThread]);
}
});
NSLog(@"异步1 end %@",[NSThread currentThread]);
NSLog(@"**************异步1 end ***************");
}
执行结果::::
2017-12-20 12:58:01.304660+0800 DeadThread[8552:2189332] **************异步1 start ***************
2017-12-20 12:58:01.304867+0800 DeadThread[8552:2189332] 异步1 start <NSThread: 0x600000078940>{number = 1, name = main}
2017-12-20 12:58:01.304959+0800 DeadThread[8552:2189332] 异步1 end <NSThread: 0x600000078940>{number = 1, name = main}
2017-12-20 12:58:01.304993+0800 DeadThread[8552:2189855] 异步1 <NSThread: 0x600000272140>{number = 3, name = (null)}
2017-12-20 12:58:01.305164+0800 DeadThread[8552:2189332] **************异步1 end ***************
2017-12-20 12:58:01.305184+0800 DeadThread[8552:2189855] 异步1 <NSThread: 0x600000272140>{number = 3, name = (null)}
2017-12-20 12:58:01.305255+0800 DeadThread[8552:2189855] 异步1 <NSThread: 0x600000272140>{number = 3, name = (null)}
得到的结果:::
1.不影响主线程的执行;
2.新任务的代码,在新的线程执行;
1.2.2 异步方法2
- (void)asyncTwo{
NSLog(@"**************异步2 start ***************");
NSLog(@"异步2 start %@",[NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
// 异步执行
dispatch_async(queue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"异步2 %@",[NSThread currentThread]);
}
});
NSLog(@"异步2 end %@",[NSThread currentThread]);
NSLog(@"**************异步2 end ***************");
}
执行结果:::
2017-12-20 13:16:36.866651+0800 DeadThread[8737:2276498] **************异步2 start ***************
2017-12-20 13:16:36.866783+0800 DeadThread[8737:2276498] 异步2 start <NSThread: 0x600000076540>{number = 1, name = main}
2017-12-20 13:16:36.866890+0800 DeadThread[8737:2276498] 异步2 end <NSThread: 0x600000076540>{number = 1, name = main}
2017-12-20 13:16:36.866891+0800 DeadThread[8737:2276887] 异步2 <NSThread: 0x608000079800>{number = 3, name = (null)}
2017-12-20 13:16:36.866960+0800 DeadThread[8737:2276498] **************异步2 end ***************
2017-12-20 13:16:36.866980+0800 DeadThread[8737:2276887] 异步2 <NSThread: 0x608000079800>{number = 3, name = (null)}
2017-12-20 13:16:36.867038+0800 DeadThread[8737:2276887] 异步2 <NSThread: 0x608000079800>{number = 3, name = (null)}
得到结果:::
1.不影响主线程的执行;
2.新任务的代码,在新的线程执行;
iOS 多线程的简单理解(1) 方式 :同步 异步的更多相关文章
- iOS 多线程的简单理解(3)执行方式 + 执行对列 的组合
通过对前面两偏线程理解的总结,自己对线程的理解也逐渐加深,梳理的清晰起来…… 通常在使用线程 的时候,都是要用到 执行对列,执行方式,执行任务, 现在开始新一轮的深入 3. 1. 1 同步 + 串行 ...
- iOS 多线程的简单理解(4) 线程锁的简单使用
要用到多线程 ,就不得不考虑,线程之间的交互,线程是否安全 推荐一个原文链接 是关于 线程锁的基本使用的 http://blog.csdn.net/qq_30513483/article/detai ...
- iOS 多线程的简单理解(2) 队列 :串行 ,并行,MainQueue,GlobalQueue
多线程队列是装载线程任务的队形结构.(系统以先进先出的方式调度队列中的任务执行 FIFO).在GCD中有两种队列: 串行队列.并发队列. 队列 :串行队列.并发队列,全局主对列,全局并发队列 2.1. ...
- C#多线程的简单理解
一.CLR线程池基础 创建和销毁线程是一个昂贵的操作,所以CLR管理了一个线程池(thread pool),可以将线程池看成一个黑盒. CLR初始化时,线程池中是没有线程的.线程的初始化与其他线程一样 ...
- iOS On-Demand Resources简单理解
ios9引入了一个新功能,On-Demand Resources,它是app thinning 的一部分.这个机能简单的说,就是在下载app的时候,app中包含的不重要资源不下载,等到需要时,在由系统 ...
- ios -RunLoop(简单理解)
一. RunLoop简介 RunLoop字面意思是运行时,即跑圈得意思.它可以在我们需要的时候自己跑起来运行,在我们没有操作的时候就停下来休息,充分节省CPU资源,提高程序性能. 二. RunLoop ...
- iOS NSRunloop的简单理解
最近学习了下NSRunloop. 作一下简单的理解: 1.runloop与线程的关系,每一个线程创建是都会有伴有一个runloop诞生,runloop用来接收事件源,让线程执行事件.当没有事件处理时, ...
- iOS:GCD理解1(同步-异步、串行-并行)
1.并行-异步(ST1与ST2抢占资源) 1-1).获取 并行(全局)队列 ,DISPATCH_QUEUE_PRIORITY_DEFAULT 为默认优先级. dispatch_queue_t queu ...
- ios多线程的几种创建方式以及基本使用
1.第一种,NSThread方法,此方法使用很少! 2.NSOperation,面向对象的多线程技术 3. NSObject多线程技术 4.苹果推荐使用的GCD技术 5.GDC中的队列
随机推荐
- 洛谷 P1279 字串距离 题解
每日一题 day24 打卡 Analysis 字符串+dp 仔细观察发现,对于f[i][j],它的值为以下三个值中的最小者: f[i-1][j]+k //a[i]对应空格 f[i][j-1]+k // ...
- 数据库访问优化之四:减少数据库服务器CPU运算
1.使用绑定变量 绑定变量是指SQL中对变化的值采用变量参数的形式提交,而不是在SQL中直接拼写对应的值. 非绑定变量写法:Select * from employee where id=123456 ...
- CSS精灵图(王者荣耀案例)
首先,我们应该知道引入精灵图的原因: 具体是因为,网页上面的每张图片都要经历一次请求才能展示给用户,小的图标频繁的请求服务器,降低页面的加载速度,为了有效地减少服务器接收和发送请求的次数,提高页面的加 ...
- 删除tppabs,href="javascript:if(confirm)...",、/*tpa=http://...
扒网站,据说是web从业人员的必备技能; 废话不多,下面应该是你想要的; 1: tppabs="h[^"]*" 2: href="javascript\:i ...
- 桥接模式:探索JDBC底层实现
一.目录概要 二.问题探究 需求:假设要设计一个电脑商场管理系统的某个模块设计,电脑分为品牌和类型两个纬度,我们应该怎么解决? 按照初学者的思路,利用继承就能简单粗暴的实现,那我们来看下这种思路的设计 ...
- Ubuntu16.4 内核降级
.cp /etc/apt/sources.list /etc/apt/sources.list.bak #备份sources.list .vi /etc/apt/sources.list #在sour ...
- 【洛谷】P1275 魔板(暴力&思维)
题目描述 有这样一种魔板:它是一个长方形的面板,被划分成n行m列的n*m个方格.每个方格内有一个小灯泡,灯泡的状态有两种(亮或暗).我们可以通过若干操作使魔板从一个状态改变为另一个状态.操作的方式有两 ...
- 解决tecplot中壁面速度不为0的问题
当直接将fluent的.cas文件和.dat文件导入tecplot中进行后处理的时候,我们会发现,壁面速度不为0的情况(见上图). 出现这样问题的原因为:fluent的计算数据是存储在每个单元的中心位 ...
- Parse发布Bolts,一个面向iOS和Android的底层库集合
转载自:http://www.infoq.com/cn/news/2014/02/parse-announces-bolts 数月前,Parse被Facebook收购.最近,它开源了一个面向iOS和A ...
- Perl看完这个,再不敢说自己会玩贪吃蛇
某天闲逛时看见一副动图: 真的是非常贪吃,各种拐弯各种吃,感觉十分有趣. 用Perl来实现自动吃满,蓄谋已久,之前的字符贪吃蛇.深度优先算法.A*算法,都是为此篇做铺垫. 那么,怎样让蛇不吃到自己呢? ...