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

第一个例子


这个例子演示了IO性能方面的一些问题。稍后我会通过多线程技术来加速代码的执行效率。我的例子很简单:

  • 在第一个测试中,我会在一个table view中加载和显示一序列图片。然后,我会向你演示滚动性能时的问题:你不能滚动表格直到当前状态的所有图片全部返回。

  • 在第二个测试中,我会使用多线程加速程序的执行。你会看到,当你在等待图片加载时,滚动性能将变得更好。



注意:对于这两种情况,我的例子不会缓存图片,这样是为了让你更清晰的看到这两者的不同。



表格6-1展示的测试结果,是基于Core Animation测试的结果,你可以在一个真实的环境下看到应用的测试结果。


表格6-1的是在iPhone OS上处理和运行应用中,加载时的fps。你可以看到多线程能够显著的加速加载的过程。在没有使用多线程的情况中,加载过程会阻塞UI,你的应用将会被挂起。


我将会给你看一下源代码,在深入解释概念之前我会做一些简单的解释。Listing 6-1 是第一个测试的原代码。


Listing 6–1. First Benchmark; This Code Runs Inside the UITableViewDataSource’s Method.


- (UITableViewCell *)tableView:(UITableView *)tableView

cellForRowAtIndexPath:(NSIndexPath *)indexPath {

       static NSString *CellIdentifier = @"Cell";

       UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

       if (cell == nil) {

               cell = [[UITableViewCell alloc]      initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:CellIdentifier];

       }

       NSURL *imageURL = [NSURL URLWithString:[self.imagesArray objectAtIndex:indexPath.row]];

       cell.imageView.image = [UIImage imageWithData:[NSData     dataWithContentsOfURL:imageURL]];

   // Configure the cell.

    return cell;

}


Listing 6-2 只是显示了在异步代码中返回图片的通常做法。为了简单起见,事实上异步代码没有在这边显示或讨论。


Listing 6–2. Second Benchmark—Getting the Image Through a Background Thread

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {

       static NSString *CellIdentifier = @"Cell";

       ImageCell *cell = (ImageCell *) [UIUtilities getCellWithTableView:tableViewcellIdentifier:CellIdentifiernibName:@"ImageCell"];

       // Configure the cell.

       NSURL *imageURL = [NSURL URLWithString:[self.imagesArrayobjectAtIndex:indexPath.row]];

       [cell.contentImage displayImageWithURL:imageURL];

      return cell;

}


#import <Foundation/Foundation.h>#import "ImageFetcher.h"

@interface UIImageView (Network) <ImageFetcherDelegate>

       - (void)displayImageWithURL:(NSURL *)url;

@end


#import "UIImageView+Network.h"#import "ImageFetcher.h"

@implementation UIImageView (Network)

- (void)imageFetcherFinished:(ImageFetcher *)fetcher {

       self.image = fetcher.image;

}

- (void)displayImageWithURL:(NSURL *)url {

       self.image = nil;
       if (url) {

           // This code will run in the background thread and callback when it retrieves// image
           [ImageFetcher loadImageWithURL:url delegate:self];

       }

}

@end


在第一个测试中,方法的内部返回了table view的cell,我在这里获取了图片。对于这行代码,iOS将会停止,然后等待图片从网络返回。之后,它继续返回cell和把cell显示给UI。这个等待过程使得应用停止,这也就是在第一个测试中你不能快速滚动table view的原因。


对于第二个测试,我使用了异步代码,它是多线程的另一种形式,但是底层库将会为你处理多线程代码。通过这段代码,主进程从等待下载完成的进程中解放出来。因此,在第二个测试中,你可以滚动table view,而没有任何问题。


多线程的好处


在iPhone应用中,你一些情况你应该考虑使用多线程。

  • 利用所有的内核和处理器:(一个处理器总是有多个内核,而内核实际上是计算单元。)目前,iPhone 4 只有一个处理器和内核,但是iPhone 5 可能会有更多的内核,那么你将能够利用所有可用的处理器来提升你应用的性能。

  • 建模:你可能想尝试从真实世界的行为中进行建模。例如,考虑这么一种解决方案,你有12种不同类型的任务要做(解决bug,面试系统管理员,创建你的下一个产品演示幻灯片,等等),另外一种是只有一个复杂的任务(解决12个bug)。后一种解决方案很简单,你只有一个工作队列去完成。第一种情况是比较复杂的解决方案,你可以为每一个任务分配一个线程。

  • 处理IO任务:通常,IO(网络和文件)任务需要花费时间来返回数据给应用。因此,如果你使用一个线程来处理,你的应用会停止工作,花费时间来等待数据。使用多线程可以帮助你把IO线程进行分割,等它接收到所有数据之后在合并到主线程中。

  • 更灵敏的UI响应:所有d的GUI应用,比如iPhone,启动的时候只有一个线程,意味着所有应用的代码都是通过main event loop(也叫着main run loop)来执行的。event loop就是当应用收到用户的输入事件(比如,单击,滑动,双击),然后会运行这个输入事件响应的逻辑。应用在event loop执行的时间越长,UI反应就越不灵敏。

  • 在后台进行一些逻辑处理:这同样是iPhone应用代码中非常重要的一部分。在某些情况下你可能需要处理一些大数据,比如运行一个XML解析算法来解析数据。这同样跟UI的响应有关:在UI线程做的工作越少,程序就会有越好的用户体验。




本文出自 “移动开发” 博客http://ikinglai.blog.51cto.com/6220785/1259271

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值