美文网首页
iOS 使用多线程

iOS 使用多线程

作者: 黑马饮清泉 | 来源:发表于2016-04-02 22:21 被阅读246次

    iOS 中实现多线程的方法有很多,基于C的有pthread,GCD,基于OC的有NSThread,NSOperationQueue,后者是前者的封装,执行效率较差,推荐使用GCD,下面介绍下开启线程的方法。

    pthread

    // 创建线程    
    pthread_t myRestrict;    
    pthread_create(&myRestrict, NULL, run, NULL);
    // 方法实现
    void *run(void *data){   
        for (int i = 0; i<10000; i++){                                           
           NSLog(@"%d---%@", i, [NSThread currentThread]);    
        }    
        return NULL;
    }   
    

    Thread

    方法一
    // 创建线程   
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download:) object:@"http://b.png"];    
    thread.name = @"下载线程";      
    // 启动线程(调用self的download方法)    
    [thread start];
    
    - (void)download:(NSString *)url{   
        NSLog(@"下载---%@---%@", url, [NSThread currentThread]);
    }
    
    方法二
    [NSThread detachNewThreadSelector:@selector(download:) toTarget:self withObject:@"http://a.jpg"];
    
    - (void)download:(NSString *)url{   
        NSLog(@"下载---%@---%@", url, [NSThread currentThread]);
    }
    
    方法三
    // 这2个不会创建线程,在当前线程中执行
    // [self performSelector:@selector(download:) withObject:@"http://c.gif"];
    // [self download:@"http://c.gif"]; 
    // 这个方法会创建线程      
    [self performSelectorInBackground:@selector(download:) withObject:@"http://c.gif"];
    
    - (void)download:(NSString *)url{   
        NSLog(@"下载---%@---%@", url, [NSThread currentThread]);
    }
    

    GCD

    async : 并发队列(最常用)
    会不会创建线程:会,一般同时开多条
    任务的执行方式:并发执行

    // 获得全局的并发队列    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);       
    // 将任务添加全局队列中去异步执行    
    dispatch_async(queue, ^{       
     NSLog(@"-----下载图片1---%@", [NSThread currentThread]);    
    });    
    dispatch_async(queue, ^{        
    NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    

    async : 串行队列(有时候用)
    会不会创建线程:会,一般只开1条线程
    任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)

    // 1.创建一个串行队列   
    dispatch_queue_t queue = dispatch_queue_create("cn.test.queue", NULL);       
    // 2.将任务添加到串行队列中 异步 执行    
    dispatch_async(queue, ^{        
    NSLog(@"-----下载图片1---%@", [NSThread currentThread]);    
    });   
     dispatch_async(queue, ^{        
    NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    // 3.非ARC,需要释放创建的队列
    // dispatch_release(queue);
    

    async -- 主队列(很常用)

    // 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)    
    dispatch_queue_t queue = dispatch_get_main_queue();       
    // 2.添加任务到主队列中异步执行(结果还是串行)    
    dispatch_async(queue, ^{       
         NSLog(@"-----下载图片1---%@", [NSThread currentThread]);    
    });    
    dispatch_async(queue, ^{        
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    

    sync -- 主队列(不能用---会卡死)

    NSLog(@"syncMainQueue----begin--");       
    // 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)    
    dispatch_queue_t queue = dispatch_get_main_queue();       
    // 2.添加 任务 到主队列中 同步 执行    
    dispatch_sync(queue, ^{        
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);    
    });    
    dispatch_sync(queue, ^{        
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    

    sync -- 并发队列
    会不会创建线程:不会
    任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
    并发队列失去了并发的功能

    // 获得全局的并发队列    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);       
    // 将 任务 添加到 全局并发队列 中 同步 执行    
    dispatch_sync(queue, ^{        
        NSLog(@"-----下载图片1---%@", [NSThread currentThread]);    
    });   
    dispatch_sync(queue, ^{        
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    

    sync -- 串行队列
    会不会创建线程:不会
    任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)

    // 创建一个串行队列    
    dispatch_queue_t queue = dispatch_queue_create("cn.text.queue", NULL);      
     // 将 任务 添加到 串行队列 中 同步 执行   
     dispatch_sync(queue, ^{       
         NSLog(@"-----下载图片1---%@", [NSThread currentThread]);   
     });    
    dispatch_sync(queue, ^{        
        NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
    });
    

    NSOperationQueue

    基本用法

    // 1.创建一个队列(非主队列)   
     NSOperationQueue *queue = [[NSOperationQueue alloc] init];       
    // 2.添加操作到队列中(自动异步执行任务,并发)    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{        
       NSLog(@"下载图片1---%@", [NSThread currentThread]);    
    }];    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{        
       NSLog(@"下载图片2---%@", [NSThread currentThread]);    
    }];       
    [queue addOperation:operation1];   
    [queue addOperation:operation2];   
    [queue addOperationWithBlock:^{       
    NSLog(@"下载图片3---%@", [NSThread currentThread]);}];       
    // 2个操作并发执行
    

    最大并发数

    // 1.创建一个队列(非主队列)
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    // 2.设置最大并发(最多同时并发执行3个任务)
     queue.maxConcurrentOperationCount = 3;
    // 3.添加操作到队列中(自动异步执行任务,并发)    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{        
        NSLog(@"下载图片1---%@", [NSThread currentThread]);    
    }];    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{       
         NSLog(@"下载图片2---%@", [NSThread currentThread]);   
     }];   
     NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{        
        NSLog(@"下载图片3---%@", [NSThread currentThread]);
    }];
    NSInvocationOperation *operation4 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
    
    [queue addOperation:operation1];    
    [queue addOperation:operation2];    
    [queue addOperation:operation3];
    [queue addOperation:operation4];
       
    [queue addOperationWithBlock:^{
          NSLog(@"下载图片5---%@", [NSThread currentThread]);    }];    
    [queue addOperationWithBlock:^{        
    NSLog(@"下载图片6---%@", [NSThread currentThread]);
        }];
    //[queue cancelAllOperations];
    

    设置依赖

    /**  假设有A、B、C三个操作,
    要求:1. 3个操作都异步执行     
         2. 操作C依赖于操作B    
         3. 操作B依赖于操作A     
    **/       
    // 1.创建一个队列(非主队列)   
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];       // 2.创建3个操作    
    NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{        
        NSLog(@"A1---%@", [NSThread currentThread]);    
    }];    
    //    [operationA cancel];//取消单个    
    //    [operationA addExecutionBlock:^{    
    //     NSLog(@"A2---%@", [NSThread currentThread]);    
    //    }];       
    //    [operationA setCompletionBlock:^{    
    //        NSLog(@"AAAAA---%@", [NSThread currentThread]);    
    //    }];       
    NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{        
    NSLog(@"B---%@", [NSThread currentThread]);    
    }];   
     NSBlockOperation *operationC = [NSBlockOperation blockOperationWithBlock:^{        
    NSLog(@"C---%@", [NSThread currentThread]);   
     }];       
    // 设置依赖    
    [operationB addDependency:operationA];    
    [operationC addDependency:operationB];       
    // 3.添加操作到队列中(自动异步执行任务)    
    [queue addOperation:operationC];    
    [queue addOperation:operationA];    
    [queue addOperation:operationB];
    

    异步回主线程

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];       
    [queue addOperationWithBlock:^{        
      // 1.异步下载图片       
      NSURL *url = [NSURL   URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];        
      NSData *data = [NSData dataWithContentsOfURL:url];        
      UIImage *image = [UIImage imageWithData:data];               
      // 2.回到主线程,显示图片(三种方法)//        
      [self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];
    //  dispatch_async(dispatch_get_main_queue(), ^{
    //            
    //        });        
      [[NSOperationQueue mainQueue] addOperationWithBlock:^{            
        self.imageView.image = image;        
      }];
    }];
    

    NSInvocationOperation

    // 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    // 创建操作
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
     // operation直接调用start,是同步执行(在当前线程执行操作)
    // [operation start];
       
    // 添加操作到队列中,会自动异步执行
    [queue addOperation:operation];
    

    相关文章

      网友评论

          本文标题:iOS 使用多线程

          本文链接:https://www.haomeiwen.com/subject/eufulttx.html