iOS开发之Run Loop
1、概述
(1) Run Loop提供了一种异步执行代码的机制,不能并行执行任务。
(2) 在主队列中,Main Run Loop直接配合任务的执行,负责处理UI事件、计时器,以及其它内核相关事件。
(3) Run Loop的主要目的是保证程序执行的线程不会被系统终止。
Run Loop的工作特点:
(1) 当有事件发生时,Run Loop会根据具体的事件类型通知应用程序做出响应。
(2) 当没有事件发生时,Run Loop会进入休眠状态,从而达到省电的目的。
(3) 当事件再次发生时,Run Loop会被重新唤醒,处理事件。
主线程和其他线程中的Run Loop:
iOS程序的主线程默认已经配置好了Run Loop,其他线程默认情况下没有设置Run Loop。
一般在开发中很少会主动创建RunLoop,而通常会把事件添加到RunLoop中。
loop示意图:
2、UIApplication中的Run Loop
3、多线程中的循环引用
如果self对象持有操作对象的引用,同时操作对象当中又直接访问了self时,才会造成循环引用。
单纯在操作对象中使用self不会造成循环引用。
注意:此时不能使用(weakSelf)
4、多线程中的资源共享
并发编程中许多问题的根源就是在多线程中访问共享资源。资源可以是一个属性、一个对象、网络设备或者一个文件等。
在多线程中任何一个共享的资源都可能是一个潜在的冲突点,必须精心设计以防止这种冲突的发生。
资源共享示例:
5、互斥锁(@synchronized)
互斥锁使用注意:
(1)加互斥锁,在共享资源的“读”“写”范围添加互斥锁
(2)要让锁的范围尽可能小!
(3)资源抢夺做简单的做法就是使用互斥锁@synchronized
(4)使用互斥锁,会变慢,互斥锁的代价十分高昂!
加上互斥锁就可以使一个资源在同一时间只能被一个线程访问,只有这个资源被这个线程用完后其他线程才能访问。
互斥锁用法:
@synchronized(self) {
//线程操作
}
例如:
@interface MJViewController ()
@property (weak, nonatomic) IBOutlet UITextView *infoText;
// 票数,若使用原子锁,只需在互斥锁的基础上把下面nonatomic改为atomic即可
@property (nonatomic, assign) NSInteger tickets;
@end
@implementation MJViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
// 卖票循环,一直卖完为止
- (void)doSaleLoop:(NSString *)opName
{
// 所有线程进入都可以循环卖票
while (YES) {
@synchronized(self) {
if (self.tickets > 0) {
--self.tickets;
NSLog(@"剩余票数 %d - %@ - %@", self.tickets, opName, [NSThread currentThread]);
} else {
break;
}
}
//-----------------------------------------
// 模拟休眠,跟资源抢夺无关,不用放在锁里
if ([opName isEqualToString:@"OP 1"]) {
[NSThread sleepForTimeInterval:1.0f];
} else {
[NSThread sleepForTimeInterval:0.3f];
}
}
}
#pragma mark 模拟多人卖票
#pragma mark GCD实现
- (IBAction)doSale:(id)sender
{
// 做多线程开始时,永远不要相信一次运行的结果
self.tickets = 20;
// 1. 队列
dispatch_queue_t q = dispatch_queue_create("sale", DISPATCH_QUEUE_CONCURRENT);
// 2. 添加任务
dispatch_async(q, ^{
[self doSaleLoop:@"OP 1"];
});
dispatch_async(q, ^{
[self doSaleLoop:@"OP 2"];
});
dispatch_async(q, ^{
[self doSaleLoop:@"OP 3"];
});
dispatch_async(q, ^{
[self doSaleLoop:@"OP 4"];
});
}
@end
【备注】在iOS中还有一种锁的功能,原子锁 —— 多读单写的锁(128位自旋锁),也会消耗性能。
原子锁只保护写入时的数据正确,而读取不负责。
对于要写入的资源,保护“写入数据”的正确性重要,还是读取的准确性重要!
如果只是开发单写多读的功能,只需要使用原子锁即可。
@synchronized 性能消耗非常的大,苹果官方不建议使用。
在实际开发中,不要去抢夺资源!
*** 并发编程最主要的目的是提高性能,让更多的代码同时运行,达到并发运行,提高整体性能的目的!
*** 手机开发最主要的是流畅,并行,至于资源抢夺的功能开发是属于服务端的范畴!
iOS开发之Run Loop的更多相关文章
- 李洪强iOS开发之RunLoop的原理和核心机制
李洪强iOS开发之RunLoop的原理和核心机制 搞iOS之后一直没有深入研究过RunLoop,非常的惭愧.刚好前一阵子负责性能优化项目,需要利用RunLoop做性能优化和性能检测,趁着这个机会深入研 ...
- iOS开发之Xcode常用调试技巧总结
转载自:iOS开发之Xcode常用调试技巧总结 最近在面试,面试过程中问到了一些Xcode常用的调试技巧问题.平常开发过程中用的还挺顺手的,但你要突然让我说,确实一脸懵逼.Debug的技巧很多,比如最 ...
- iOS开发之Socket通信实战--Request请求数据包编码模块
实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数 据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncS ...
- iOS开发之UISearchBar初探
iOS开发之UISearchBar初探 UISearchBar也是iOS开发常用控件之一,点进去看看里面的属性barStyle.text.placeholder等等.但是这些属性显然不足矣满足我们的开 ...
- iOS开发之UIImage等比缩放
iOS开发之UIImage等比缩放 评论功能真不错 评论开通后,果然有很多人吐槽.谢谢大家的支持和关爱,如果有做的不到的地方,还请海涵.毕竟我一个人的力量是有限的,我会尽自己最大的努力大家准备一些干货 ...
- iOS开发之 Xcode6 添加xib文件,去掉storyboard的hello world应用
iOS开发之 Xcode6.1创建仅xib文件,无storyboard的hello world应用 由于Xcode6之后,默认创建storyboard而非xib文件,而作为初学,了解xib的加载原理 ...
- iOS开发之loadView、viewDidLoad及viewDidUnload的关系
iOS开发之loadView.viewDidLoad及viewDidUnload的关系 iOS开发之loadView.viewDidLoad及viewDidUnload的关系 标题中所说的3个方 ...
- iOS开发之info.pist文件和.pch文件
iOS开发之info.pist文件和.pch文件 如果你是iOS开发初学者,不用过多的关注项目中各个文件的作用.因为iOS开发的学习路线起点不在这里,这些文件只会给你学习带来困扰. 打开一个项目,我们 ...
- iOS开发之WKWebView简单使用
iOS开发之WKWebView简单使用 iOS开发之 WKWebVeiw使用 想用UIWebVeiw做的,但是突然想起来在iOS8中出了一个新的WKWebView,算是UIWebVeiw的升级版. ...
随机推荐
- asp.net权限认证:OWIN实现OAuth 2.0 之密码模式(Resource Owner Password Credential)
asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...
- jquery mobile多页面跳转等,data-ajax="false" 问题,
当我们的网站引用了jquery mobile的js后,点击页面的链接,你会发现页面无法跳转,因为jquery mobile默认是采用ajax方式来加载网站的,如果你需要跳到另一个页面,需要在a标签加上 ...
- Java内部类之匿名内部类
我们都知道Java中可以使用内部类,将一个类的定义放在另一个类的定义的内部,这就是内部类,但是匿名内部类往往使我们摸不着头脑,因为它并没有特定的名称,那么该如何使用它呢? 定义一个匿名内部类 pu ...
- 报表学习总结(一)——ASP.NET 水晶报表(Crystal Reports)的简单使用
一.水晶报表简介 Crystal Reports(水晶报表)是一款商务智能(BI)软件,主要用于设计及产生报表.水晶报表是业内最专业.功能最强的报表系统,它除了强大的报表功能外.最大的优势是实现了与绝 ...
- 众人拾柴火焰高之Tomcat集群
一人拾柴火不旺,众人拾柴火焰高.Tomcat服务器也是一样,一台服务器再强大能承受的访问也是有限的.要提供高并发.高可用的服务,就必须横向扩展,多台Tomcat组成一个集群,根据实际的访问量动态增减服 ...
- 基于canvas的二维码邀请函生成插件
去年是最忙碌的一年,实在没时间写博客了,看着互联网行业中一个又一个人的倒下,奉劝大家,健康要放在首位,保重身体.好了,言归正传,这是17年的第一篇博文,话说这天又是产品同学跑过来问我说:hi,lenn ...
- 使用rsync+inotify-tools+ssh实现文件实时同步
假设某服务器架构中有两台web服务器(IP为192.168.1.252和192.168.1.254),一台代码更新发布服务器(IP为192.168.1.251),需要同步的目录是/data/www/, ...
- 【译文】什么是Docker
What is Docker? By Tim Butler • 14 May 2015 • https://www.conetix.com.au/blog/what-is-docker Unless ...
- jvm的内存空间分区
在方法(代码块)中定义一个变量时,java就在栈中为这个变量分配JVM内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的JVM内存空间:而在堆中分配的JVM内存由java虚拟机的自动 ...
- struts2接收参数的5种方法
以下形式中最常用的是前两种 1. 使用Action的属性: 在action 里面定义要接收的参数,并提供相应的setter,getter,和提交参数的名称一致, 并不用做数据类型的转换相应提交方式可以 ...