[iOS]深入浅出 iOS 之多线程 NSThread
OS 支持多个层次的多线程 编程,层次越高的抽象程度越高,使用起来也越方便,也是苹果最推荐使用的方法。
下面简要说明这三种不同范式:
Thread 是这三种范式里面相对轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程 之间的同步。线程 共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。
你得协调多个线程 对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。在 iOS 中我们可以使用多种形式的 thread:
Cocoa threads: 使用NSThread 或直接从 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程 。如果你选择thread来实现多线程 ,那么 NSThread 就是官方推荐优先选用的方式。
POSIX threads: 基于 C 语言的一个多线程 库,
Cocoa operati*****是基于 Obective-C实现的,类 NSOperation 以面向对象的方式封装了用户需要执行的操作,我们只要聚焦于我们需要做的事情,而不必太操心 线程 的管理,同步等事情,
因为NSOperation已经为我们封装了这些事情。 NSOperation 是一个抽象基类,我们必须使用它的子类。iOS 提供了两种默认实现:NSInvocationOperation 和 NSBlockOperation。
Grand Central Dispatch : iOS4 才开始支持,它提供了一些新的特性,以及运行库来支持多核并行编程,它的关注点更高:如何在多个 cpu 上提升效率。
有了上面的总体框架,我们就能清楚地知道不同方式所处的层次以及可能的效率,便利性差异。下面我们先来看看 NSThread 的使用,包括创建,启动,同步,通信等相关知识。这些与 win32/Java 下的 thread 使用非常相似。
线程 创建与启动
NSThread的创建主要有两种直接方式:
[NSThread detachNewThreadSelector:@selector(myThreadMainMethod:) toTarget:self withObject:nil];
和
NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:@selector(myThreadMainMethod:)
object:nil];
[myThread start];
这两种方式的区别是:前一种一调用就会立即创建一个 线程 来做事情;而后一种虽然你 alloc 了也 init了,但是要直到我们手动调用 start 启动线程 时才会真正去创建线程 。
这种延迟实现思想在很多跟资源相关的地方都有用到。后一种方式我们还可以在启动线程 之前,对线程 进行配置,比如设置 stack 大小,线程 优先级。
还有一种间接的方式,更加方便,我们甚至不需要显式编写 NSThread 相关代码。那就是利用 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个 线程 :
[myObj performSelectorInBackground:@selector(myThreadMainMethod) withObject:nil];
其效果与 NSThread 的 detachNewThreadSelector:toTarget:withObject: 是一样的。
线程 同步
线程 的同步方法跟其他系统下类似,我们可以用原子操作,可以用 mutex,lock等。
iOS的原子操作函数是以 OSAtomic开头的,比如:OSAtomicAdd32, OSAtomicOr32等等。这些函数可以直接使用,因为它们是原子操作。
iOS中的 mutex 对应的是 NSLock,它遵循 NSLooking协议,我们可以使用 lock, tryLock, lockBeforeData:来加锁,用 unLock来解锁。使用示例:
BOOL moreToDo = YES;
NSLock *theLock = [[NSLock alloc] init];
...
while (moreToDo) {
/* Do another increment of calculation */
/* until there’s no more to do. */
if ([theLock tryLock]) {
/* Update display used by all threads. */
[theLock unlock];
}
}
我们可以使用指令 @synchronized 来简化 NSLock的使用,这样我们就不必显示编写创建NSLock,加锁并解锁相关代码。
- (void)myMethod:(id)anObj
{
@synchronized(anObj)
{
// Everything between the braces is protected by the @synchronized directive.
}
}
还有其他的一些锁对象,比如:循环锁NSRecursiveLock,条件锁NSConditionLock,分布式锁NSDistributedLock等等,在这里就不一一介绍了,大家去看官方文档吧。
用NSCodition同步执行的顺序
NSCodition 是一种特殊类型的锁,我们可以用它来同步操作执行的顺序。它与 mutex 的区别在于更加精准,等待某个 NSCondtion 的线程 一直被 lock,直到其他线程 给那个 condition 发送了信号。
下面我们来看使用示例: 某个线程 等待着事情去做,而有没有事情做是由其他线程 通知它的。
[cocoaCondition lock];
while (timeToDoWork <= 0)
[cocoaCondition wait];
timeToDoWork--;
// Do real work here.
[cocoaCondition unlock];
其他 线程 发送信号通知上面的线程 可以做事情了:
[cocoaCondition lock];
timeToDoWork++;
[cocoaCondition signal];
[cocoaCondition unlock];
线程 间通信
线程 在运行过程中,可能需要与其它线程 进行通信。我们可以使用 NSObject 中的一些方法:
在应用程序主线程 中做事情:
performSelectorOnMainThread:withObject:waitUntilDone:
performSelectorOnMainThread:withObject:waitUntilDone:modes:
在指定 线程 中做事情:
performSelector:onThread:withObject:waitUntilDone:
performSelector:onThread:withObject:waitUntilDone:modes:
在当前 线程 中做事情:
performSelector:withObject:afterDelay:
performSelector:withObject:afterDelay:inModes:
取消发送给当前 线程 的某个消息
cancelPreviousPerformRequestsWithTarget:
cancelPreviousPerformRequestsWithTarget:selector:object:
如在我们在某个 线程 中下载数据,下载完成之后要通知主线程 中更新界面等等,可以使用如下接口:- (void)myThreadMainMethod
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// to do something in your thread job
...
[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];
[pool release];
}
RunLoop
说到 NSThread 就不能不说起与之关系相当紧密的 NSRunLoop。Run loop 相当于 win32 里面的消息循环机制,它可以让你根据事件/消息(鼠标消息,键盘消息,计时器消息等)来调度线程 是忙碌还是闲置。
系统会自动为应用程序的主线程 生成一个与之对应的 run loop 来处理其消息循环。在触摸 UIView 时之所以能够激发 touchesBegan/touchesMoved 等等函数被调用,
就是因为应用程序的主线程 在 UIApplicationMain 里面有这样一个 run loop 在分发 input 或 timer 事件。
[iOS]深入浅出 iOS 之多线程 NSThread的更多相关文章
- iOS开发:Swift多线程NSThread的使用
一:创建线程,NSThread创建线程常用的三种方式: //1:手动创建启动 let thread:NSThread = NSThread(target: self, selector:"d ...
- 【转】深入浅出 iOS 之生命周期
[iOS]深入浅出 iOS 之生命周期 深入浅出 iOS 之生命周期 http://blog.csdn.net/kesalin/article/details/6691766 罗朝辉(http:// ...
- iOS的三种多线程技术NSThread/NSOperation/GCD
1.iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的"并发"技术,使得程序员可以不再去关心 ...
- IOS 多线程 NSThread
一个正在运行的应用程序是一个进程,一个进程会默认开启一个主线程,但是在主线程中的操作是串行的,也就是当有多个任务同时需要完成的时候,是按照顺序一个个执行.因此,为了提高效率,会在进程中开启多个线程,每 ...
- iOS多线程 NSThread/GCD/NSOperationQueue
无论是GCD,NSOperationQueue或是NSThread, 都没有线程安全 在需要同步的时候需要使用NSLock或者它的子类进行加锁同步 "] UTF8String], DISPA ...
- (转)深入浅出 iOS 之生命周期
原文:http://www.cocoachina.com/applenews/devnews/2011/0817/3129.html 深入浅出 iOS 之生命周期 发布于:2011-08-17 10: ...
- Objective-C 高级编程:iOS与OS X多线程和内存管理
<Objective-C 高级编程:iOS与OS X多线程和内存管理> 基本信息 原书名: Pro Multithreading and Memory Management for iOS ...
- iOS开发网络篇—多线程断点下载
iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始, ...
- 深入浅出--iOS的TCP/IP协议族剖析&&Socket
深入浅出--iOS的TCP/IP协议族剖析&&Socket 简介 该篇文章主要回顾--TCP/IP协议族中的TCP/UDP.HTTP:还有Socket.(--该文很干,酝酿了许久! ...
随机推荐
- javascript设计模式-工厂模式
简单工厂模式:使用一个类来生成实例. 复杂工厂模式:使用子类来决定一个成员变量应该是哪个具体的类的实例. 简单工厂模式是由一个方法来决定到底要创建哪个类的实例, 而这些实例经常都拥有相同的接口.通过工 ...
- 把jqmobi 變成jQuery 的插件 從此使用jQuery
因為項目的要求,需要用到jQuery 的一些插件 ,而我又是用jqmobi的....o(╯□╰)o 看看文檔.....把jqmobi 變成jQuery的插件 問題就解決了 O(∩_∩)O哈哈~ 官 ...
- js 函数function的几种形式
//有的时候我们一直都在使用函数,但是却不知道函数使用的正真含义 //其中一个重要的目的是为了提高代码的复用率 //其二函数可以传递参数并有返回值 //函数声明 //不带参数,不带返回值 functi ...
- Oracle笔记 九、PL/SQL 游标的使用
--演示隐式游标,系统自动声明,自动打开,自动使用并且自动关闭 begin update emp set sal = 1000; dbms_output.put_line('影响的行数:' || sq ...
- SQL Server 数据库基础编程
Ø Go批处理语句 用于同时执行多个语句 Ø 使用.切换数据库 use master go Ø 创建.删除数据库 方法1. --判断是否存在该数据库,存在就删除 if (exists ...
- how to extract and decrypt WeChat EnMicromsg.db on Android phone
One of my friend came to me with an Android phone. She saild somehting wrong with the hardware of he ...
- 设计模式-中介者模式(Mediator)
场景分析: 众所周知,电脑有很多组成部分,如硬盘.内存.光驱.音频.键盘等,各个组件之间协同工作才能保证电脑的正常运行. 如果各个组件之间直接交互,可能会比较复杂,如下图: 将上面的各个组件抽象成类, ...
- c#学习之Socket网络编程
我是新手以前没写过博客 希望大家勿喷, 在编写Socket的时候需要导入System.Net.Socket 命名空间.利用该类我们可以直接编写Socket的客户端和服务的的程序了, 这里我们只讲tpc ...
- 关于ASP.net TextBox控件的失去焦点后触发其它事件
编写人:CC阿爸 2015-2-02 今天在这里,我想与大家一起分享如何处理的ASP.net TextBox控件的失去焦点后触发其它事件的问题,在此做个小结,以供参考.有兴趣的同学,可以一同探讨与学习 ...
- ubuntu下svn使用指南
ubuntu下安装subversion客户端: sudo apt-get install subversion subversion-tools 详细请看 http://www.subversion. ...