IOS多线程编程笔记与NSRunLoop学习

本文探讨了macOS和iOS中的多线程技术,包括OperationObjects、DispatchQueue及NSRunLoop的作用与配置。深入分析了RunLoop如何管理线程事件,解释了事件源、定时器和运行模式的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多线程与NSLoop笔记;
1.虽然operation objects和dispatch queue提供了更加现代化的多核并发操作,但mac os和iOS也提供直接操作和管理线程的接口,如果正在创建新的应用程序,苹果建议我们使用gcd或operation objects;除此之外还有:
1)idle-time notifications,当前程序的run loop空闲时会发出该通知,适合处理一些低优先级的短作业;
2)调用系统提供的异步api,不需要自己去考虑线程层次的问题;
3)定时器;
4)分离的单独进程;在某些时候需要使用,比如需要特定权限的作业可能需要另起进程。
2.mac os/ios中使用到的线程技术包括:
1)cocoa threads;这是oc的类库,主要有NSThread类;
2)POSIX threads;这是c的函数库,支持POSIX接口,POSIX标准定义了操作系统应该为应用程序提供的接口标准,POSIX标准意在期望获得源代码级别的软件可移植性。换句话说,为一个POSIX兼容的操作系统编写的程序,应该可以在任何其它的POSIX操作系统上编译执行。POSIX并不局限于UNIX。许多其它的操作系统,例如DEC OpenVMS支持POSIX标准;
3.一个run loop是用来在线程上管理事件异步到达的基础设施。一个run loop为线程监测一个或多个事件源。当事件到达的时候,系统唤醒线程并调度事件到run loop,然后分配给指定程序。如果没有事件出现和准备处理,run loop把线程置于休眠状态。配置run loop需要:
1)创建并启动线程;
2)获取run loop的对象引用;
3)设置事件处理程序,并告诉run loop运行;
4.cocoa会自动为你的主线程配置run loop,如果你打算创建长时间运行的辅助线程,你必须为你的线程配置相应的run loop。使用run loop 的目的是让你的线程在有工作的时候忙于工作,而没工作的时候处于休眠状态。
5.run loop的管理并不完全自动,你仍然需要设计你的线程代码在合适的时候启动run loop并正确响应输入事件。你的代码要提供实现循环部分的控制语句,换言之就是要有while或for循环语句来驱动run loop。在你的循环中,使用run loop object来运行事件处理代码,它响应接收到的事件并启动已经安装的处理程序。
6.仅当在为你的程序创建辅助线程的时候,你才可能需要显式运行一个run loop,一般不需要使用,了解其概念即可,只有如下情况才可能需要使用:
1)使用端口或自定义输入源和其它线程通信;
2)使用线程的定时器;
3)Cocoa中使用任何performSelector…的方法;
4)使线程周期性工作;

7.总体而言Run loop和线程编程的内容比较难懂,可以在遇到维护类似代码时,去参考苹果的多线程编程文档,新写的代码都不再使用之为好,加上dispatch sources可代替Run loop的情况下,更加没有必要使用之。NSRunLoop对象比CFRunLoop的c函数更加易于使用,可以获取currentRunLoop并调用addPort:forMode或addTimer:forMode往它上面添加事件,不过它是非线程安全的,也就是不要在NSRunLoop所在的线程之外去获取和改变其它属性,可能结果无法预知。

8.简单的runloop与thread的关系可以理解为,runloop负责管理线程while循环中的部分代码,线程在while中通过判断runloop是否有输入等的条件,runloop所封装的代码块等来达到一直循环处理事件的效果,同时runloop在没有事件时,也可以通知线程休眠。

【摘录网上找到的资料,感觉比较能理解】RunLoop

RunLoop从字面上看是运行循环的意思,这一点也不错,它确实就是一个循环的概念,或者准确的说是线程中的循环。 本文一开始就提到有些程序是一个圈,这个圈本质上就是这里的所谓的RunLoop,就是一个循环,只是这个循环里加入很多特性。 
首先循环体的开始需要检测是否有需要处理的事件,如果有则去处理,如果没有则进入睡眠以节省CPU时间。 所以重点便是这个需要处理的事件,在RunLoop中,需要处理的事件分两类,一种是输入源,一种是定时器,定时器好理解就是那些需要定时执行的操作,输 入源分三类:performSelector源,基于端口(Mach port)的源,以及自定义的源。编程的时候可以添加自己的源。RunLoop还有一个观察者Observer的概念,可以往RunLoop中加入自己的 观察者以便监控着RunLoop的运行过程,CFRunLoop.h中定义了所有观察者的类型:

  1. enum CFRunLoopActivity { kCFRunLoopEntry = (1 << 0), kCFRunLoopBeforeTimers = (1 << 1), kCFRunLoopBeforeSources = ( 

如果你使用过select系统调用写过程序你便可以快速的理解runloop事件源的概念,本质上讲事件源的机制和select一样是一种多路复用IO的 实现,在一个线程中我们需要做的事情并不单一,如需要处理定时钟事件,需要处理用户的触控事件,需要接受网络远端发过来的数据,将这些需要做的事情统统注 册到事件源中,每一次循环的开始便去检查这些事件源是否有需要处理的数据,有的话则去处理。 拿具体的应用举个例子,NSURLConnection网络数据请求,默认是异步的方式,其实现原理就是创建之后将其作为事件源加入到当前的 RunLoop,而等待网络响应以及网络数据接受的过程则在一个新创建的独立的线程中完成,当这个线程处理到某个阶段的时候比如得到对方的响应或者接受完 了网络数据之后便通知之前的线程去执行其相关的delegate方法。所以在Cocoa中经常看到scheduleInRunLoop:forMode: 这样的方法,这个便是将其加入到事件源中,当检测到某个事件发生的时候,相关的delegate方法便被调用。对于CoreFoundation这一层而 言,通常的模式是创建输入源,然后将输入源通过CFRunLoopAddSource函数加入到RunLoop中,相关事件发生后,相关的回调函数会被调 用。如CFSocket的使用。 另外RunLoop中还有一个运行模式的概念,每一个运行循环必然运行在某个模式下,而模式的存在是为了过滤事件源和观察者的,只有那些和当前 RunLoop运行模式一致的事件源和观察者才会被激活。

每一个线程都有其对应的RunLoop,但是默认非主线程的RunLoop是没有运行的,需要为RunLoop添加至少一个事件源,然后去run它。一般情况下我们是没有必要去启用线程的RunLoop的,除非你在一个单独的线程中需要长久的检测某个事件。


内容概要:本文针对国内加密货币市场预测研究较少的现状,采用BP神经网络构建了CCi30指数预测模型。研究选取2018年3月1日至2019年3月26日共391天的数据作为样本,通过“试凑法”确定最优隐结点数目,建立三层BP神经网络模型对CCi30指数收盘价进行预测。论文详细介绍了数据预处理、模型构建、训练及评估过程,包括数据归一化、特征工程、模型架构设计(如输入层、隐藏层、输出层)、模型编译训练、模型评估(如RMSE、MAE计算)以及结果可视化。研究表明,该模型在短期内能较准确地预测指数变化趋势。此外,文章还讨论了隐层节点数的优化方法及其对预测性能的影响,并提出了若干改进建议,如引入更多技术指标、优化模型架构、尝试其他时序模型等。 适合人群:对加密货币市场预测感兴趣的研究人员、投资者及具备一定编程基础的数据分析师。 使用场景及目标:①为加密货币市场投资者提供一种新的预测工具和方法;②帮助研究人员理解BP神经网络在时间序列预测中的应用;③为后续研究提供改进方向,如数据增强、模型优化、特征工程等。 其他说明:尽管该模型在短期内表现出良好的预测性能,但仍存在一定局限性,如样本量较小、未考虑外部因素影响等。因此,在实际应用中需谨慎对待模型预测结果,并结合其他分析工具共同决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值