zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Python 函数装饰器简明教程
    *arg和**kwarg的区别
    克里金插值
    C语言Hello world
    ibatis错误
    typealias
    视图
    权限分级设置
    走出浮躁的泥沼:学会享受学习过程的乐趣
    R语言 eval(quote(x)) 和 eval(x)
  • 原文地址:https://www.cnblogs.com/sayimba/p/5664914.html
Copyright © 2011-2022 走看看