关于多线程三种语句的实现

       之前做的一些作业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中执行加载图片、更新视图,不过语句相对复杂,不太易理解。

      

      三种方式,多多少少还是会容易记混,还是择其中特性进行相应的记忆。


版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-09-01 10:59  温柔的天空  阅读(303)  评论(0编辑  收藏  举报