iOS多线程介绍
一.线程概述
有些程序是一条直线,起点到终点;有些程序是一个圆,不断循环,直到将它切断。直线的如简单的Hello World,运行打印完,它的生命周期便结束了,像昙花一现那样;圆如操作系统,一直运行直到你关机。 
一个运行着的程序就是一个进程或者叫做一个任务,一个进程至少包含一个线程,线程就是程序的执行流。Mac和iOS中的程序启动,创建好一个进程的同时, 一个线程便开始运行,这个线程叫主线程。主线程在程序中的地位和其他线程不同,它是其他线程最终的父线程,且所有界面的显示操作即AppKit或 UIKit的操作必须在主线程进行。 
系统中的每一个进程都有自己独立的虚拟内存空间,而同一个进程中的多个线程则共用进程的内存空间。每创建一个新的线程,都需要一些内存(如每个线程有自己的Stack空间)和消耗一定的CPU时间。另外当多个线程对同一个资源出现争夺的时候需要注意线程安全问题。
二.创建线程
创建一个新的线程就是给进程增加了一个执行流,执行流总得有要执行的代码吧,所以新建一个线程需要提供一个函数或者方法作为线程的入口。
1.使用NSThread
NSThread提供了创建线程的途径,还可以提供了检测当前线程是否是主线程的方法。 使用NSThread创建一个新的线程有两种方式:
- 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 Taobao.com. Al
三.多线程进阶
NSOperation&NSOperationQueue
很多时候我们使用多线程,需要控制线程的并发数,毕竟线程也是消耗系统资源的,当程序中同时运行的线程过多时,系统必然变慢。 所以很多时候我们会控制同时运行线程的数目。
NSOperation可以封装我们的操作,然后将创建好的NSOperation对象放到NSOperationQueue中,OperationQueue便开始启动新的线程去执行队列中的操作,OperationQueue的并发度是可以通过如下方式进行设置:
- - (void)setMaxConcurrentOperationCount:(NSInteger)count
GCD
GCD是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(imageDownloa
当然,GCD除了处理多线程外还有很多非常好的功能,其建立在强大的kqueue之上,效率也能够得到保障。
四.线程间通信
线程间通信和进程间通信从本质上讲是相似的。线程间通信就是在进程内的两个执行流之间进行数据的传递,就像两条并行的河流之间挖出了一道单向流动长沟,使得一条河流中的水可以流入另一条河流,物质得到了传递。
1.performSelect On The Thread
框架为我们提供了强制在某个线程中执行方法的途径,如果两个非主线程的线程需要相互间通信,可以先将自己的当前线程对象注册到某个全局的对象中去,这样相 互之间就可以获取对方的线程对象,然后就可以使用下面的方法进行线程间的通信了,由于主线程比较特殊,所以框架直接提供了在出线程执行的方法。
- @interface NSObject (NSThreadPerformAdditions) - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUnti
       2.Mach Port 
在苹果的Thread Programming Guide的Run Pool一节的Configuring a Port-Based Input Source 这一段中就有使用Mach Port进行线程间通信的例子。 其实质就是父线程创建一个NSMachPort对象,在创建子线程的时候以参数的方式将其传递给子线程,这样子线程中就可以向这个传过来的 NSMachPort对象发送消息,如果想让父线程也可以向子线程发消息的话,那么子线程可以先向父线程发个特殊的消息,传过来的是自己创建的另一个 NSMachPort对象,这样父线程便持有了子线程创建的port对象了,可以向这个子线程的port对象发送消息了。
当然各自的port对象需要设置delegate以及schdule到自己所在线程的RunLoop中,这样来了消息之后,处理port消息的delegate方法会被调用,你就可以自己处理消息了。
五.RunLoop
RunLoop从字面上看是运行循环的意思,这一点也不错,它确实就是一个循环的概念,或者准确的说是线程中的循环。 本文一开始就提到有些程序是一个圈,这个圈本质上就是这里的所谓的RunLoop,就是一个循环,只是这个循环里加入很多特性。 
首先循环体的开始需要检测是否有需要处理的事件,如果有则去处理,如果没有则进入睡眠以节省CPU时间。 所以重点便是这个需要处理的事件,在RunLoop中,需要处理的事件分两类,一种是输入源,一种是定时器,定时器好理解就是那些需要定时执行的操作,输 入源分三类:performSelector源,基于端口(Mach port)的源,以及自定义的源。编程的时候可以添加自己的源。RunLoop还有一个观察者Observer的概念,可以往RunLoop中加入自己的 观察者以便监控着RunLoop的运行过程,CFRunLoop.h中定义了所有观察者的类型:
- 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的,除非你在一个单独的线程中需要长久的检测某个事件。
iOS多线程介绍的更多相关文章
- [转] iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用
		介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统.这建立在任务并行执行的线程池模式的基础上的.它首 ... 
- iOS多线程主题
		下面是:2个并发进程.和2个并发线程的示意图: 下面介绍三种多线程技术(Thread.Cocoa Operation.Grand Central Dispatch): 1.最轻量级Thread(需要自 ... 
- iOS多线程技术方案
		iOS多线程技术方案 目录 一.多线程简介 1.多线程的由来 2.耗时操作的模拟试验 3.进程和线程 4.多线程的概念及原理 5.多线程的优缺点和一个Tip 6.主线程 7.技术方案 二.Pthrea ... 
- iOS多线程到底不安全在哪里?
		iOS多线程安全的概念在很多地方都会遇到,为什么不安全,不安全又该怎么去定义,其实是个值得深究的话题. 共享状态,多线程共同访问某个对象的property,在iOS编程里是很普遍的使用场景,我们就从P ... 
- iOS多线程的详情使用示例--简进祥
		大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操作只能 ... 
- iOS多线程
		关于iOS多线程 概述 这篇文章中,我不会说多线程是什么.线程和进程的区别.多线程有什么用,当然我也不会说什么是串行.什么是并行等问题,这些我们应该都知道的. 在 iOS 中其实目前有 4 套多线程方 ... 
- iOS多线程学习及总结
		能有份网上的存储资料,备以后提升及参考 iOS 多线程编程 简介 一. iOS有三种多线程编程的技术,分别是: 1. NSThread 2. Cocoa NSOp ... 
- iOS多线程杂论
		iOS多线程的分布 (1) NSThread (2) NSOperation (3) GCD 现在对下面三个进行一个个的分析,希望那里说得不对的地方希望简友们帮我指点一二. 1,NSThread 优点 ... 
- iOS多线程开发
		概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操 ... 
随机推荐
- react-native 的微信SDK辅助包,支持微信登录、微信分享、微信支付
			微信SDK集成示例,现已完成微信授权登录,之后将陆续包装分享等其他功能. ReactNative高级交流群 127482131 或访问 http://blog.1ygowu.com ReactNat ... 
- Objective-c内存管理
			cocoa中的内存管理机制 引用计数 每一个对象都拥有一个引用计数 当对象创建的时候,引用计数的值是1 当发生retain消息时,该对象的引用计数+1,该对象的引用计数为2 当向这个对象发送relea ... 
- 20135306黄韧[2.72  2.77  3.70](http://i.cnblogs.com/EditPosts.aspx?opt=1)
			2.72 A.size_t是无符号整数,因此左边都会先转换为无符号整数,它肯定是大于等于0的. B.判断条件改为 if(maxbytes > 0 && maxbytes > ... 
- C#  GC 垃圾回收机制
			今天来谈谈C# 的GC ,也就是垃圾回收机制,非常的受教,总结如下 首先:谈谈托管,什么叫托管,我的理解就是托付C# 运行环境帮我们去管理,在这个运行环境中可以帮助我们开辟内存和释放内存,开辟内存一般 ... 
- 第十章 使用MapKit
			本项目是<beginning iOS8 programming with swift>中的项目学习笔记==>全部笔记目录 ------------------------------ ... 
- iOS -- 给model赋值时走了[self setValuesForKeysWithDictionary:dic]不走setvalue: forked:
			这是一个小坑, 看看你的BaseModel的便利构造器的方法: + (__kindof BaseModel *)modelWithDic:(NSDictionary *)dic { return [[ ... 
- nginx 的源码安装
			安装nginx之前要做的准备工作有:安装如下库 (1)gzip模块需要 zlib 库 (2)rewrite模块需要 pcre 库 (3)ssl 功能需要openssl库 还有一种简单的方法就是 yum ... 
- 【前端学习】搬进Github
			学习参考 萌码 一.Github简介和基本操作 Github 上操作基本上围绕一个个项目展开.项目就是一个文件夹,在github中成为“仓库”(repository),里面放着所有的项目文件,可以是代 ... 
- 【UVA 1451】Average
			题 题意 求长度为n的01串中1占总长(大于L)的比例最大的一个子串起点和终点. 分析 前缀和s[i]保存前i个数有几个1,[j+1,i] 这段区间1的比例就是(s[i]-s[j])/(i-j),于是 ... 
- sql prompt5安装好了 也破解完成了 然后到SQL里面 还是没有提示 是为什么?
			勾上这个,祝你成功! 
