zoukankan      html  css  js  c++  java
  • iOS中的多线程NSThread/GCD/NSOperation & NSOperationQueue

    iOS多线程有四套多线程方案:

    • Pthreads
    • NSThread
    • GCD
    • NSOperation & NSOperationQueue

    接下来我来一个一个介绍他们

    Pthreads

    在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthreads作为操作系统的线程。
    这套多线程是使用C语言实现的,所以可移植性很高。但是在实际项目中基本上不会用到,这里只做简单的介绍。
    首先要包含头文件pthread.h

    void *star(void *data)
    {
        NSLog(@"%@",[NSThread currentThread]);
        return NULL;
    }
    - (IBAction)buttonTouch:(id)sender
    {
        pthread_t thread;
        pthread_create(&thread, NULL, star, NULL);
    }

    控制台输出:

    2016-09-07 14:37:44.734 GCDDemo[2660:1124576] <NSThread: 0x7fd2024a58a0>{number = 2, name = (null)}

    NSThread

    NSThread是苹果封装的面向对象处理多线程的方案。但是他却不够智能,需要我们手动的管理线程的生命周期以及同步。所以这套方案我们通常也不常用。
    创建线程:

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(thisThread) object:nil];
    [thread start];

    或者使用类方法

    [NSThread detachNewThreadSelector:@selector(thisThread) toTarget:self withObject:nil];

    或者使用NSObject的类方法:

    [self performSelector:@selector(thisThread)];

    但是NSThread需要使用NSLock来给线程上锁。以及进行其他操作,它不够智能。所以我们只在很少的情况使用它

    GCD

    GCD全称Grand Central Dispatch。是苹果提出的多核并行运算的解决方案。也就是说他会自动利用多核CPU,它会自动管理线程的生命周期。只需要我们告诉他应该做什么。
    在GCD中有两个概念,一个是任务,一个是队列

    • 任务就是一串代码,在GCD中使用的Block。只需要将需要做的事情添加到Block里面就行了。任务有两种执行方式同步或者异步
      • 同步执行:会一直阻塞当前线程直到任务处理完。
      • 异步执行:不会阻塞当前线程。当前线程会直接往下处理,直到该任务作出反应。
    • 队列可以理解为用于存放任务的容器,队列分为串行队列并行队列两种
      • 串行队列:放在串行队列中的任务会遵循先入先出的原则,在当前线程中一个一个按顺序执行。
      • 并行队列:放在并行队列中的任务虽然也会遵循先入先出的原则,但是会开不同的线程让他们同时执行。不过同时执行的数量也会受到系统资源的限制。

    创建队列

    • 主队列:主队列是一条串行队列,用于刷新UI。
      dispatch_queue_t queue = dispatch_get_main_queue();
      NSLog(@"%@",queue);
      控制台输出

      2016-09-08 14:15:25.361 GCDDemo[6984:2309204] <OS_dispatch_queue: com.apple.main-thread[0x10c34e9c0]>

    • 用户的队列:用户可以自己创建串行队列或者并行队列。
      dispatch_queue_t queue = dispatch_queue_create("wodeduilie", NULL);
      NSLog(@"%@",queue);
      这个函数有两个参数,一个是队列名,第二个参数控制是否为串行或者并行。第二个参数传入DISPATCH_QUEUE_SERIAL或者NULL表示串行。DISPATCH_QUEUE_CONCURRENT表示并行。

      创建任务

    • 同步任务:会阻塞当前进程
      dispatch_queue_t queue = dispatch_queue_create("wodeduilie", NULL);
      dispatch_sync(queue, ^{
          NSLog(@"%@",[NSThread currentThread]);
      });
    • 异步任务:不会阻塞当前线程
      dispatch_queue_t queue = dispatch_queue_create("wodeduilie", NULL);
      dispatch_async(queue, ^{
          NSLog(@"%@",[NSThread currentThread]);
      });

    NSOperation & NSOperationQueue

    NSOperation是面向对象的,它是对GCD的封装。NSOperationNSOperationQueue分别对应GCD任务队列

    创建任务

    NSOperation是抽象类,如果你想使用它需要使用它的子类:

    • NSInvocationOperation通过绑定方法来封装任务:
      NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(thisThread) object:nil];
      [operation start];
    • NSBlockOperation通过Block来封装任务:
      NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"%@",[NSThread currentThread]);
        }];
      [operation start];
      NSBlockOperation中还有一个方法addExecutionBlock:来添加多个任务,而且这些任务是并发执行的

    控制台输出:

    2016-09-08 22:21:26.660 GCDDemo[8112:2598032] <NSThread: 0x7fd151607d20>{number = 1, name = main}

    你需要使用start方法或者cancel方法来开始或者取消一个任务。

    创建队列

    NSOperationQueue中只有两种队列,一个是主队列,一个是自己创建的其他队列:

    • 主队列就是我们用于刷新UI的:

      NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"%@",[NSThread currentThread]);
      }];
      NSOperationQueue *queue = [NSOperationQueue mainQueue];
      [queue addOperation:operation];

      控制台输出:

      2016-09-08 22:36:33.053 GCDDemo[8279:2611844] <NSThread: 0x7f828b6020c0>{number = 1, name = main}

    • 其他队列就是用于我们进行耗时操作的队列:

      NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"%@",[NSThread currentThread]);
      }];
      NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      [queue addOperation:operation];

      控制台输出:

      2016-09-08 22:40:49.459 GCDDemo[8405:2616956] <NSThread: 0x7f8833e2fd30>{number = 2, name = (null)}

      我们使用自定义的队列的时候,加入该队列的任务会自动的并发执行。但是有一个参数表示最大并发执行的数量maxConcurrentOperationCount
      当我们将这个参数设为1时就是串行队列。
      在NSOperationQueue中我们还可以直接使用方法添加任务

      - (void)addOperationWithBlock:(void (^)(void))block;

      只要我们将任务添加到队列中就会自动执行任务的start方法。

    原文链接:http://www.jianshu.com/p/162ba1b0c495
  • 相关阅读:
    拥有自己的代码生成器—Newlife.XCode模板编写教程
    基于Newlife.XCode的权限系统(含数据集权限)【设计篇】
    拥有自己的代码生成器—NewLife.XCode代码生成器分析
    利用javascript来转换GB2312到UNICONDE &#形式
    和荣笔记 从 Unicode 到 GB2312 转换表制作程式
    如何做SVN迁移
    和荣笔记 GB2312 字符集和编码说明
    asp对象化之:基于adodb.stream的文件操作类
    Unicode 汉字内码表
    微软建议的ASP性能优化28条守则 之三
  • 原文地址:https://www.cnblogs.com/Mr-zyh/p/5856051.html
Copyright © 2011-2022 走看看