[iOS]深入浅出 iOS 之多线程 NSThread

http://www.cocoachina.com/bbs/read.php?tid=43852

OS 支持多个层次的多线程 编程,层次越高的抽象程度越高,使用起来也越方便,也是苹果最推荐使用的方法。 
 
 
下面简要说明这三种不同范式:  
Thread 是这三种范式里面相对轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程 之间的同步。线程 共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。 
你得协调多个线程 对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。在 iOS 中我们可以使用多种形式的 thread: 
Cocoa threads: 使用NSThread 或直接从 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程。如果你选择thread来实现多线程 ,那么 NSThread 就是官方推荐优先选用的方式。 
POSIX threads: 基于 C 语言的一个多线程 库, 
 
Cocoa operations是基于 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]; 
    } 
}

lock 阻塞等待

trylock 非阻塞

我们可以使用指令 @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:

就是取消执行的延迟函数,像[self performSelector:@selector(sendTest) withObject:nilafterDelay:10.0]; 就不在执行了

- (void) networkReachabilityDidUpdate:(NetworkReachability*)reachability

{

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(reachabilityChanged) object:nil];

[self performSelector:@selector(reachabilityChanged) withObject:nil afterDelay:0.1f];

}

cancelPreviousPerformRequestsWithTarget是终止上次performSelector的Delay调用

上面例子是防止在afterDelay时间内重复调用reachabilityChanged

如在我们在某个 线程 中下载数据,下载完成之后要通知主线程 中更新界面等等,可以使用如下接口:

- (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 事件。

时间: 2024-10-07 05:31:23

[iOS]深入浅出 iOS 之多线程 NSThread的相关文章

iOS多线程 NSThread/GCD/NSOperationQueue

http://www.cnblogs.com/kenshincui/p/3983982.html iOS开发系列--并行开发其实很容易 2014-09-20 23:34 by KenshinCui, 9738 阅读, 19 评论, 收藏,  编辑 --多线程开发 概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操作只能一步步按顺序逐个执行.改变这种

iOS的三种多线程技术NSThread/NSOperation/GCD

1.iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的"并发"技术,使得程序员可以不再去关心线程的具体使用问题 NSOperation/NSOperationQueue 面向对象的线程技术 GCD -- Grand Central Dispatch(派发) 是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术. 以上这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,

IOS UI多线程 NSThread 下载并显示图片到UIImageView

效果图 @property (weak,nonatomic)IBOutletUILabel *downLabelInfo; @property (weak,nonatomic)IBOutletUIImageView *imageView; @end @implementationViewController - (void)viewDidLoad { [super viewDidLoad]; NSString *url  [email protected]"http://d.hiphotos.b

iOS 多线程 NSThread NSOperation NSOperationQueue GCD 线程锁 线程阻塞

iPhone中的线程应用并不是无节制的,官方给出的资料显示,iPhone OS下的主线程的堆栈大小是1M,第二个线程开始就是512KB,并且该值不能通过编译器开关或线程API函数来更改,只有主线程有直接修改UI的能力,所以一些数据层面可以开辟线程来操作进行,iOS线程的操作方法有NSThread NSOperation NSOperationQueue GCD: NSThread方法有 //NSThread自动 - (IBAction)didClickNSThreadAutoButtonActi

iOS进阶面试题----多线程

本文转载至 http://blog.csdn.net/xunyn/article/details/14525243 ios面试题多核并发应用 iOS面试题系列: iOS如何面试 iOS面试题(一) iOS基础面试题(二) iOS基础面试题(三) iOS基础面试题(四) iOS进阶面试题----Block部分 1 多线程是什么 多线程是个复杂的概念,按字面意思是同步完成多项任务,提高了资源的使用效率,从硬件.操作系统.应用软件不同的角度去看,多线程被赋予不同的内涵,对于硬件,现在市面上多数的CPU

iOS并发编程对比总结,NSThread,NSOperation,GCD - iOS

1. 多线程概念 进程 正在进行中的程序被称为进程,负责程序运行的内存分配 每一个进程都有自己独立的虚拟内存空间 线程 线程是进程中一个独立的执行路径(控制单元) 一个进程中至少包含一条线程,即主线程 可以将耗时的执行路径(如:网络请求)放在其他线程中执行 创建线程的目的就是为了开启一条新的执行路径,运行指定的代码,与主线程中的代码实现同时运行 1.1 多任务系统调度示意图 说明:每个应用程序由操作系统分配的短暂的时间片(Timeslice)轮流使用CPU,由于CPU对每个时间片的处理速度非常快

iOS开发之网络多线程

iOS开发之网络多线程 1. pthred (POSIX) 一般情况不用 2. NSThread NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(dealThreadExit:) object:nil]; [thread1 start]; [NSThread detachNewThreadSelector:@selector(detailTextLabel) toTarget:self wi

iOS 面试题之多线程是什么?

面试官:你给我讲讲多线程吧. 我:多线程,就是多线程呗... 要是都这么回答,还有多少人要你. ===================================================== 首先分析多线程的使用环境: 多线程处理包括Core Data的多线程访问,UI的并行绘制,异步网络请求以及一些在运行态内存吃紧的情况下处理大文件的方案等. 其次,分别举例说明iOS提供的多线程的实现方法 iOS中提供了以下集中中多线程的实现方式 1.NSOBjcet实现 // 最简单的多线程 执

深入浅出iOS事件机制

深入浅出iOS事件机制 2015年 04月 12日 本文章将讲解有关iOS事件的传递机制,如有错误或者不同的见解,欢迎留言指出.转载自:http://zhoon.github.io/ios/2015/04/12/ios-event.html iOS的事件有好几种:Touch Events(触摸事件).Motion Events(运动事件,比如重力感应和摇一摇等).Remote Events(远程事件,比如用耳机上得按键来控制手机),其中最常用的应该就是Touch Events了,基本存在于每个a