成都网站建设设计

将想法与焦点和您一起共享

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

你的线程入口

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名与空间、虚拟空间、营销软件、网站建设、砚山网站维护、网站推广。

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

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

有很多事情你需要记住:

  • Autorelease pool:管理autorelease对象

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

  • RunLoop:创建事件处理代码

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

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

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

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中监听一个输入流:

  1. NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    [iStream setDelegate:self];
    [iStream scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];

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

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

  1. [NSTimer scheduledTimerWithTimeInterval:2.0target:self

    selector:@selector(doStuff)userInfo:nil

    repeats:YES];

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


文章标题:iOS使用多线程提高数据并发访问之五
网页链接:http://chengdu.cdxwcx.cn/article/pegcdo.html