thread、operation、GCD

//  ViewController.m
#import "ViewController.h"

@interface ViewController ()
{
    //任务队列,能够自动管理多个任务(NSOperation的对象)
    NSOperationQueue *_operationQueue;
}
@end

@implementation ViewController

#define kUrlString @"http://jsonfe.funshion.com/?pagesize=10&cli=iphone&page=1&src=phonemedia&ta=0&ver=1.2.8.2&jk=0"
#define kImageString @"http://img1.funshion.com/attachment/fs/112/200/112200.jpg?1387939530"

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    _operationQueue = [[NSOperationQueue alloc] init];
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btn setTitle:@"thread" forState:UIControlStateNormal];
    [btn setFrame:CGRectMake(10,30,300,50)];
    [btn addTarget:self action:@selector(threadMethod) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
    
    
    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btn1 setTitle:@"operation" forState:UIControlStateNormal];
    [btn1 setFrame:CGRectMake(10,90,300,50)];
    [btn1 addTarget:self action:@selector(operationMethod) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn1];
    
    UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btn2 setTitle:@"GCD" forState:UIControlStateNormal];
    [btn2 setFrame:CGRectMake(10,150,300,50)];
    [btn2 addTarget:self action:@selector(gcdMethod) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn2];
    
    /*严重的费时操作  等好久才能显示
        for (int i=0; i<20; i++) {
            for (int j=0; j<50; j++) {

    NSURL *url  =[NSURL URLWithString:kImageString];
    //同步下载数据的方法
    NSData *data = [NSData dataWithContentsOfURL:url];
   // UIImage *ima = [UIImage imageWithData:data];
                UIImageView *ima=[[UIImageView alloc]initWithFrame:CGRectMake(0+j*3, i*3, 2, 2)];
                ima.image=[UIImage imageWithData:data];
        [self.view addSubview:ima];
            }
        }
     */
}

//gcd是iOS4.0之后出现的技术,Grand Centeral Dispatch->苹果高度封装的处理多线程的技术,可以理解为block版本的NSOperation和NSOperationQueue
- (void)gcdMethod{
  //gcd中有一个主队列,用于管理和调度主线程;有三个优先级的全局队列,来管理子线程
    //dispatch_get_global_queue 第一个参数为设置队列的优先级 0为默认优先级 2为最高优先级 -1为低优先级;第二个参数为预留参数,一般也写成0
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
     //利用全局队列,在主线程之外单独开辟了一个线程,线程执行block方法
        NSURL *url  =[NSURL URLWithString:kUrlString];
        NSString *result = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
        if (result) {
            //通过主队列回到主线程,主线程中执行block
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"result:%@",result);
            });
            
        }else{
            NSLog(@"error!");
        }
    });
}


//NSOperation,以任务为导向的线程,可以叫做开启一个任务
//NSOperationQueue 任务队列,来维护多个任务(线程)
- (void)operationMethod{
   //一般使用NSOperation的子类来进行多线程操作
    NSInvocationOperation *oper = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage) object:nil];
    //[oper start]; 需要调用此方法 oper对象才会开辟线程,让线程执行sel方法
    //添加到队列后,队列会自动让oper对象开辟线程并执行sel方法
   [_operationQueue addOperation:oper];
    //[_operationQueue addOperations:<#(NSArray *)#> waitUntilFinished:<#(BOOL)#>]
}
//NSThread
- (void)threadMethod{
    //NSThread iOS中最早出现的线程类
    //detachNewThreadSelector 在主线程之外单独开辟一个线程来执行sel方法
    //toTarget sel所在的对象
    [NSThread detachNewThreadSelector:@selector(downloadString) toTarget:self withObject:nil];
}

//同步下载一张图片
- (void)downloadImage{
    @autoreleasepool {
        NSURL *url  =[NSURL URLWithString:kImageString];
        //同步下载数据的方法
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:data];
        if (image) {
            //给主线程
            [self performSelectorOnMainThread:@selector(receiveImage:) withObject:image waitUntilDone:NO];
            //线程之间的通信
            //[self performSelector:<#(SEL)#> onThread:<#(NSThread *)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>]
        }else{
            NSLog(@"下载失败!");
        }
    }
}

- (void)receiveImage:(UIImage *)image{
    //colorWithPatternImage 此方法比较消耗GPU,需要慎用,而且要求view与imagesize 一致
   // self.view.backgroundColor = [UIColor colorWithPatternImage:image];
    
    
    //多线程可以解决费时操作  比普通的下载图片快很多
    for (int i=0; i<200; i++) {
        for (int j=0; j<500; j++) {
            UIImageView *ima=[[UIImageView alloc]init];
            ima.frame=CGRectMake(0+j*30, i*30, 20, 20);
            ima.image=image;
            [self.view addSubview:ima];
        }
    }
}

//线程的生命周期与函数一致,函数开始则线程开始;函数执行完毕,线程自动结束
//在主线程之外开辟的线程叫子线程或者工作线程
- (void)downloadString{
  //执行耗时操作
    //主线程的自动释放池,子线程无法使用,需要自己手动添加
    @autoreleasepool {
        NSURL *url = [NSURL URLWithString:kUrlString];
        //同步请求数据的方法,会阻塞当前线程
        NSString *result = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
        if (result) {
          //需要将数据给到UI主线程,理论上子线程没有被分配足够的资源来操作UI,所以对于UI的操作一般在主线程中完成。
         //子线程和主线程之间的通信
        [self performSelectorOnMainThread:@selector(receiveString:) withObject:result waitUntilDone:NO];
            
        //[self performSelector:<#(SEL)#> withObject:<#(id)#>]
        }else{
            NSLog(@"load error!");
        }
    }
}

//在主线程中执行的方法
- (void)receiveString:(NSString *)result{
    NSLog(@"ui result:%@",result);
    //操作UI也在主线程中
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

 

posted @ 2016-07-12 21:13  代码始我快乐  阅读(279)  评论(0编辑  收藏  举报