您的位置:首页 > 移动开发 > IOS开发

iOS使用多线程提高数据并发访问 之五

2013-11-23 00:54 411 查看
你的线程入口

当启动线程时,你需要有一些代码来管理当前线程的状态,线程创建和执行的内存,还有在线程内部抛出的异常。原因是你新创建的线程会有自己的栈,它和默认的栈是不同的,如图 6-4。因此,你线程使用的内存和主线程使用的内存是不同的。异常也类似;它只会存储在你的栈中,并不会返回到主栈和主线程中。





有很多事情你需要记住:

Autorelease pool:管理autorelease对象

ExceptionHandler:管理线程运行过程中发生的异常

RunLoop:创建事件处理代码

我会讨论为什么要实现他们已经如何实现他们。

表格6-3 提供了一个简短的演示,让你复习一下创建和配置线程的主要技术,以及他们的优缺点。





Autorelease Pool

在应用的每一个线程中,你应该总是要有一个Autorelease Pool,通过把代码放在@autorelease中块中。这个pool会包含所有的autoreleased对象,当线程运行的时候。如果你没有调用返回一个autoreleased对象的方法,最好还是包含@autorelease,因为系统底层的frameworks和libraries也会创建和返回autoreleased对象。如果你有一个@autorelease,而从没使用它,一切依然能够正常运行。

如果你通过Xcode模板创建的应用,你会看到main方法中有下面的代码:

int main(int argc, char *argv[]) {

   @autoreleasepool {

           int retVal = UIApplicationMain(argc, argv, nil, nil);

   }

   return retVal;

}

@autorelease将会处理线程内部所有的autoreleased对象。你可能已经知道,autoreleased对象是

一个你不再使用的,但是你又不想立即释放的对象。它同样可以使用类似[NSMutableArray array]这样的工厂方法来返回一个autorelease对象;。这些对象将在run loop结束时被release。

因此,如果你创建了一个新的线程,确保你的代码包裹在@autorelease块中,像这样:

- (void)myThreadMethod {

       @autoreleasepool { // Top-level pool

       // Do thread work here.

       }

}

ExceptionHandler

在处理线程时,异常是非常重要的。因为每一个线程都有它自己的栈,当发生一个异常时,它将会跟踪所有的方法直到栈的顶部。这可能导致你的线程停止运行。任何主线程中的exception handler将会被忽略。

下面是一个处理异常的基本代码:

NSObject *myObject = nil;

@try {

   // access to some objects inside an array

   myObject = [myArray objectAtIndex:2];

}

@catch ( NSException *e ) {

       NSLog(@"Array has fewer than 3 items");

}

@finally {

       // clean up code here

}

Run Loop

当你创建一个新的线程后,你有两种方法来执行它。

在线程内部编写代码来执行你的逻辑,直到任务执行完毕,而没有什么中断。比如,之前介绍过的从URL现在图片的代码。显然,这是比较简单的。

当有动态事件发生时,你想要你的线程做出响应。比如监听网络上的socket或在某个特定时间触发的事件。这和第一种情况是不同的,需要你在创建一个新的run loop。

下面是一个简单的代码,在一个RunLoop中监听一个输入流:

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];

[iStream setDelegate:self];

[iStream scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];

注意:如果[NSRunLoop currentRunLoop]方法是在一个线程中调用,而不是一个run loop,这个方法创建一个新的run loop。

如果你想要在开始运行之前,让一个run loop来等待一段时间,你可以使用NSTimer:

[NSTimer scheduledTimerWithTimeInterval:2.0target:self

selector:@selector(doStuff)userInfo:nil

repeats:YES];

但是,有些情况你不应该使用RunLoop,比如在主线程中你有事件处理代码,如NSInputStream或NSTimer工作在一些敏感的任务上,要花费很长的时间才能完成。因为事件处理代码,像我的这个例子,最终会运行在创建它的线程上,你的线程不能继续运行其他事件处理代码,直到旧的事件处理完毕。这对UI主线程是非常有害的,如果你在线程内部创建了timer或input stream run loop。主要的问题是它使得你的UI变得更不灵敏。

本文出自 “移动开发” 博客http://ikinglai.blog.51cto.com/6220785/1260394
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: