iOS开发学习之iOS多线程和RunLoop
更新时间:2023-06-04 13:21:01 阅读量: 实用文档 文档下载
- ios开发多线程面试题推荐度:
- 相关推荐
iOS多线程编程对于初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。
iOS多线程编程对于iOS开发初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。
一. 线程概述
二.创建线程
1.使用NSThread
2.使用NSObject
3.POSIX Thread
三.多线程进阶
1.NSOperation & NSOperationQueue
2.GCD
四.进程间通信
1.和主线程的通信
2.任意线程间的通信
五.RunLoop
一.线程概述
有些程序是一条直线,起点到终点;有些程序是一个圆,不断循环,直到将它切断。直线的如简单的Hello World,运行打印完,
iOS多线程编程对于初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。
它的生命周期便结束了,像昙花一现那样;圆如操作系统,一直运行直到你关机。 一个运行着的程序就是一个进程或者叫做一个任务,一个进程至少包含一个线程,线程就是程序的执行流。Mac和iOS中的程序启动,创建好一个进程的同时,一个线程便开始运行,这个线程叫主线程。主线程在程序中的地位和其他线程不同,它是其他线程最终的父线程,且所有界面的显示操作即AppKit或UIKit的操作必须在主线程进行。 系统中的每一个进程都有自己独立的虚拟内存空间,而同一个进程中的多个线程则共用进程的内存空间。每创建一个新的线程,都需要一些内存(如每个线程有自己的Stack空间)和消耗一定的CPU时间。另外当多个线程对同一个资源出现争夺的时候需要注意线程安全问题。
二.创建线程 创建一个新的线程就是给进程增加了一个执行流,执行流总得有要执行的代码吧,所以新建一个线程需要提供一个函数或者方法作为线程的入口。
1.使用NSThread
NSThread提供了创建线程的途径,还可以提供了检测当前线程是否是主线程的方法。 使用NSThread创建一个新的线程有两种方
iOS多线程编程对于初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。
式:
1.创建一个NSThread的对象,调用其start方法。对于这种方式的NSThread对象的创建,可以使用一个目标对象的方法初始化一个NSThread对象,或者创建一个继承NSThread类的子类,实现其main方法,然后在直接创建这个子类的对象。
2.使用 detachNewThreadSelector:toTarget:withObject:这个类方法创建一个线程,这个比较直接了,直接使用目标对象的方法作为线程启动入口。
2.使用NSObject
其实NSObject直接就加入了多线程的支持,允许对象的某个方法在后台运行。如: [myObj performSelectorInBackground:@selector(doSomething) withObject:nil];
复制代码
3.POSIX Thread由于Mac和iOS都是基于Darwin系统,Darwin系统的XUN内核,是基于Mach和BSD的,继承了BSD的POSIX接口,所以可以直接使用POSIX线程的相关接口来使用线程。创建线程的接口为 pthread_create,当然在创建之前可以通过相关函数设置好线程的属性。以下为POSIX线程使用简单的例子。 // // main.c // pthread // // Created by Lu Kejin on 1/27/12. // Copyright (c) 2012 . All rights reserved. //
#include <stdio.h> #include <pthread.h> #include <unistd.h>
iOS多线程编程对于初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。
void *pthreadRoutine(void *); int main (int argc, const char * argv[]) { pthread_attr_t attr; pthread_t pthreadID; int returnVal; returnVal = pthread_attr_init(&attr); returnVal = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); int threadError = pthread_create(&pthreadID, &attr, &pthreadRoutine, NULL); returnVal = pthread_attr_destroy(&attr); if (threadError != 0) { // Report an error. } sleep(10); return 0; } void *pthreadRoutine(void *data){ int count = 0; while (1) { printf("count = %d\n",count++); sleep(1); } return NULL; } 复制代码
三.多线程进阶NSOperation&NSOperationQueue很多时候我们使用多线程,需要控制线程的并发数,毕竟线程也是消耗系统资源的,当程序中同时运行的线程过多时,系统必然变慢。 所以很多时候我们会控制同时运行线程的数目。NSOperation可以封装我们的操作,然后将创建好的NSOperation对象放到
NSOperationQueue中,OperationQueue便开始启动新的线程去执行队列中的操作,OperationQueue的并发度是可以通过如下方式进行设置:
- (void)setMaxConcurrentOperationCount:(NSInteger)count
iOS多线程编程对于初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。
复制代码
GCDGCD是Grand Central Dispatch的缩写,是一系列的BSD层面的接口,在Mac 10.6 和iOS4.0以后才引入的,且现在
NSOperation和NSOperationQueue的多线程的实现就是基于GCD的。目前这个特性也被移植到FreeBSD上了,可以查看
libdispatch这个开源项目。比如一个在UIImageView中显示一个比较大的图片 dispatch_queue_t imageDownloadQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(imageDownloadQueue, ^{ NSURL *imageURL = [NSURL URLWithString:@"/test.png"]; NSData *imageData = [NSData dataWithContentsOfURL:imageURL]; UIImage *image = [UIImage imageWithData:imageData]; dispatch_async(dispatch_get_main_queue(), ^{ [imageView setImage:image];//UIKit必须在主线程执行 }); });
复制代码
当然,GCD除了处理多线程外还有很多非常好的功能,其建立在强大的kqueue之上,效率也能够得到保障。四.线程间通信线程间通信和进程间通信从本质上讲是相似的。线程间通信就是在进程内的两个执行流之间进行数据的传递,就像两条并行的河流之间挖出了一道单向流动长沟,使得一条河流中的水可以流入另一
iOS多线程编程对于初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。
条河流,物质得到了传递。1.performSelect On The Thread框架为我们提供了强制在某个线程中执行方法的途径,如果两个非主线程的线程需要相互间通信,可以先将自己的当前线程对象注册到某个全局的对象中去,这样相互之间就可以获取对方的线程对象,然后就可以使用下面的方法进行线程间的通信了,由于主线程比较特殊,所以框架直接提供了在出线程执行的方法。 @interface NSObject (NSThreadPerformAdditions) - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array; - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; // equivalent to the first method with kCFRunLoopCommonModes - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array NS_AVAILABLE(10_5, 2_0); - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0); // equivalent to the first method with kCFRunLoopCommonModes ... @end
复制代码 2.Mach Port
在苹果的Thread Programming Guide的Run Pool一节的
iOS多线程编程对于初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。
Configuring a Port-Based Input Source 这一段中就有使用Mach Port进行线程间通信的例子。 其实质就是父线程创建一个
NSMachPort对象,在创建子线程的时候以参数的方式将其传递给子线程,这样子线程中就可以向这个传过来的NSMachPort对象发送消息,如果想让父线程也可以向子线程发消息的话,那么子线程可以先向父线程发个特殊的消息,传过来的是自己创建的另一个NSMachPort对象,这样父线程便持有了子线程创建的port对象了,可以向这个子线程的port对象发送消息了。当然各自的port对象需要设置delegate以及schdule到自己所在线程的
RunLoop中,这样来了消息之后,处理port消息的delegate方法会被调用,你就可以自己处理消息了。五.RunLoopRunLoop从字面上看是运行循环的意思,这一点也不错,它确实就是一个循环的概念,或者准确的说是线程中的循环。 本文一开始就提到有些程序是一个圈,这个圈本质上就是这里的所谓的RunLoop,就是一个循环,只是这个循环里加入很多特性。 首先循环体的开始需要检测是否有需要处理的事件,如果有则去处理,如果没有则进入睡眠以节省CPU时间。 所以重点便是这个需要处理的事件,在RunLoop中,需要处理的事件分两类,一种是输入源,一种是定时器,定时器好理解就是那些需要定时执行的操作,输入源分三类:performSelector源,基于端口(Mach port)的源,以及自定义的源。编程的时候可以添加自己的源。RunLoop还有一个观察者Observer的概念,可以往RunLoop中加入自己
iOS多线程编程对于初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。
的观察者以便监控着RunLoop的运行过程,CFRunLoop.h中定义了所有观察者的类型: enum CFRunLoopActivity { kCFRunLoopEntry = (1 << 0), kCFRunLoopBeforeTimers = (1 << 1), kCFRunLoopBeforeSources = (1 << 2), kCFRunLoopBeforeWaiting = (1 << 5), kCFRunLoopAfterWaiting = (1 << 6), kCFRunLoopExit = (1 << 7), kCFRunLoopAllActivities = 0x0FFFFFFFU }; typedef enum CFRunLoopActivity CFRunLoopActivity;
复制代码
如果你使用过select系统调用写过程序你便可以快速的理解
runloop事件源的概念,本质上讲事件源的机制和select一样是一种多路复用IO的实现,在一个线程中我们需要做的事情并不单一,如需要处理定时钟事件,需要处理用户的触控事件,需要接受网络远端发过来的数据,将这些需要做的事情统统注册到事件源中,每一次循环的开始便去检查这些事件源是否有需要处理的数据,有的话则去处理。 拿具体的应用举个例子,
NSURLConnection网络数据请求,默认是异步的方式,其实现原理就是创建之后将其作为事件源加入到当前的RunLoop,而等待网络响应以及网络数据接受的过程则在一个新创建的独立的线程中完成,当这个线程处理到某个阶段的时候比如得到对方的响应或者接受完了网络数据之后便通知之前的线程去执行其相关的
iOS多线程编程对于初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。
delegate方法。所以在Cocoa中经常看到
scheduleInRunLoop:forMode:这样的方法,这个便是将其加入到事件源中,当检测到某个事件发生的时候,相关的delegate方法便被调用。对于CoreFoundation这一层而言,通常的模式是创建输入源,然后将输入源通过CFRunLoopAddSource函数加入到RunLoop中,相关事件发生后,相关的回调函数会被调用。如CFSocket的使用。 另外RunLoop中还有一个运行模式的概念,每一个运行循环必然运行在某个模式下,而模式的存在是为了过滤事件源和观察者的,只有那些和当前RunLoop运行模式一致的事件源和观察者才会被激活。每一个线程都有其对应的RunLoop,但是默认非主线程的RunLoop是没有运行的,需要为RunLoop添加至少一个事件源,然后去run它。一般情况下我们是没有必要去启用线程的RunLoop的,除非你在一个单独的线程中需要长久的检测某个事件。
本学习资料出自蓝鸥科技iOS培训,转载须注明出处。
正在阅读:
电力拖动自动控制系统复习题06-18
拉麻中学食堂食品安全自查报告11-19
六年级上册科学模拟试题第三单元03-08
大学软件测试期中考试题12-09
国外学者关于师幼关系的研究综述06-17
蒙特卡罗方法介绍MC_1-205-17
热爱生命的诗歌11-21
- 教学能力大赛决赛获奖-教学实施报告-(完整图文版)
- 互联网+数据中心行业分析报告
- 2017上海杨浦区高三一模数学试题及答案
- 招商部差旅接待管理制度(4-25)
- 学生游玩安全注意事项
- 学生信息管理系统(文档模板供参考)
- 叉车门架有限元分析及系统设计
- 2014帮助残疾人志愿者服务情况记录
- 叶绿体中色素的提取和分离实验
- 中国食物成分表2020年最新权威完整改进版
- 推动国土资源领域生态文明建设
- 给水管道冲洗和消毒记录
- 计算机软件专业自我评价
- 高中数学必修1-5知识点归纳
- 2018-2022年中国第五代移动通信技术(5G)产业深度分析及发展前景研究报告发展趋势(目录)
- 生产车间巡查制度
- 2018版中国光热发电行业深度研究报告目录
- (通用)2019年中考数学总复习 第一章 第四节 数的开方与二次根式课件
- 2017_2018学年高中语文第二单元第4课说数课件粤教版
- 上市新药Lumateperone(卢美哌隆)合成检索总结报告
- 习之
- 多线
- iOS
- RunLoop
- 开发
- 程和
- ABSTRACT Leakage Power Modeling and Optimization in Interconnection Networks
- 移动IP网络工程师
- 2007 AMJ Upper echelons theory--An update
- New solutions of relativistic wave equations in magnetic fields and longitudinal fields
- 政府职能及实现途径
- 第5章 数据透明传输技术
- 第三章 资金流转--电子商务支付
- 中学数学组教研工作计划
- 高级会计学练习题(2014.11.21)
- 中国通货膨胀的惯性变化及其货币政策含义
- 无线网络故障诊断维护_2014-04-22-16-25-55
- 别墅基坑支护工程喷射砼面层施工方法
- 浅谈高校图书馆做好新生入馆培训工作的重要性
- 简单方法帮助女人
- 梦幻西游手游狮驼新技能连环击解析 连环击使用技巧
- 考勤及休假管理制度
- 八年级下册生物(人教版)复习提纲(2013年最新整理)
- 企业即时通信UcSTAR统一通信平台产品说明
- 石湖全民健身策划书
- 周工作计划考核表学习手册