iOS使用多线程提高数据并发访问之五
你的线程入口
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名与空间、虚拟空间、营销软件、网站建设、砚山网站维护、网站推广。
当启动线程时,你需要有一些代码来管理当前线程的状态,线程创建和执行的内存,还有在线程内部抛出的异常。原因是你新创建的线程会有自己的栈,它和默认的栈是不同的,如图 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变得更不灵敏。
本文名称:iOS使用多线程提高数据并发访问之五
当前链接:http://scyanting.com/article/pegcdo.html