之前做的一些作业Demo都是单线程的。
今天学了多线程,讲了三种多线程语句。以从网上加载到客户端一张图片为例子。线程的部分相对好理解,毕竟很容易知道讲的是什么,
多线程,举个例子就是在加载图片的同时,又可以做别的操作
单线程的话,是无法做别的操作的,在加载图片的时候网速好可能看不出来,因为响应的快的话,几乎瞬间加载成功,又可以做别的操作了。要是下载的话,因为是单线程,下载这个功能独占线程,无法进行其他操作。这个时候引入多线程,将下载这个线程独立出来,与其他操作并行。
将要实现这样一个效果,点击加载的时候,测试滑动条是否能滑动
一、先看单线程的示例代码:
#pragma mark -主线程里面直接请求数据
-(void)loadImageInMainThread
{
NSURL *url = [NSURL URLWithString:KImageUrl];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
[NSThread sleepForTimeInterval:5];//...@4
self.imageView.image = img;
}
其中前三句是比较常用的从网络上加载图片的语句,@4这句是模拟下载过程的,其意思是,这个函数的线程睡眠5秒。而且这一句的作用也很大。
因为是单线程所以这一句线程睡眠就把整个线程给弄睡眠了。测试结果:睡眠(加载)过程中,是无法拖动滑动条的。
二、主要的三种多线程代码:
1、使用block(NSBlockOperation)
#pragma mark - 在新的线程中使用请求图片资源,使用block(NSBlockOperation)
-(void)loadImageUseBlockThread
{
NSBlockOperation *newThread = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:KImageUrl];
[NSThread sleepForTimeInterval:5];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
[self performSelectorOnMainThread:@selector(updateUI:) withObject:img waitUntilDone:YES];
}];
//把新建立的线程加入到queue里面
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperation:newThread];
}
-(void)updateUI:(UIImage*)img
{
self.imageView.image = img;
}
这个方式的特性在于,声明一个线程,然后把线程加入到queue(操作队列里面)。
其中,声明线程是以NSBlockOperation声明的,它继承自NSOperation,并且根本上可以看做附带一个block的函数。
block函数中包括加载图片的过程、声明UIImage对象的过程、此类调用装载更新UI函数的线程。
其中更新UI的函数单独封装。
2、使用 NSInvocationOperation
#pragma mark - 在新的线程中使用请求图片资源,使用 NSInvocationOperation
-(void)loadImageUseInvocationThread
{
//创建一个新线程,并分配任务
NSInvocationOperation *invocationThread = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadImage:) object:KImageUrl];
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperation:invocationThread];
}
-(void)loadImage:(NSString *)urlPath
{
//请求图片
NSURL *url = [NSURL URLWithString:urlPath];
[NSThread sleepForTimeInterval:2];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
//主线程去更新UI
[self performSelectorOnMainThread:@selector(updateUI:) withObject:img waitUntilDone:YES];
}
<pre name="code" class="html">-(void)updateUI:(UIImage*)img
{
self.imageView.image = img;
}
这种方式中,直接声明创建一个线程,然后把线程加入到queue
这里的创建线程只是一个运用 NSInvocationOperation声明初始化的语句。其中装载图片加载图片更新UI单独封装成一个函数作为初始化的选择所选函数。
3、使用GCD
#pragma mark - 在新的线程中使用请求图片资源 ,使用GCD
-(void)loadImageGCD
{
//创建一个新线程
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//在block中去执行新的任务
NSURL *url = [NSURL URLWithString:KImageUrl];
[NSThread sleepForTimeInterval:2];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
//在主线程中更新 UI
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = img;
});
});
}
在这里的形式也是直接用block块,在block中执行加载图片、更新视图,不过语句相对复杂,不太易理解。
三种方式,多多少少还是会容易记混,还是择其中特性进行相应的记忆。
版权声明:本文为博主原创文章,未经博主允许不得转载。