zoukankan      html  css  js  c++  java
  • GCD多线程的使用(一)

            苹果官方给的解释是:Grand Central Dispatch(GCD)是异步执行任务的技术之一。GCD的线程管理是作为系统的一部分来实现的,因此可以统一管理,也可执行任务,比以前的线程更有效率,这也是苹果推荐使用的技术。

            苹果官方对GCD的说明:开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中。这句话有三个关键点:

            1、想执行的任务。

            2、追加。

            3、适当的Dispatch Queue。

            用代码比较好说明这三点:

    dispatch_async(queue, ^{
            //想执行的任务
        });

            想执行的任务使用Block来定义,通过dispatch_async函数来将定义好的任务追加到适当的Dispatch Queue即queue中。其中,Dispatch Queue是一个dispatch_queue_t类型的变量,是通过函数dispatch_queue_create来创建,Dispatch Queue有两种类型:

            1、Serial Dispatch Queue:串行,等待现在执行中处理结束。

            2、Concurrent Dispatch Queue:并行,不等待现在执行中处理结束。

            追加也有两种方式:

            1、dispatch_sync:同步

            2、dispatch_async:异步

            所以,从现在看来,在使用GCD进行多线程编程的时候主要由以下四种:

            1、Serial Dispatch Queue+dispatch_sync

            2、Serial Dispatch Queue+dispatch_async

            3、Concurrent Dispatch Queue+dispatch_sync

            4、Concurrent Dispatch Queue+dispatch_async

            串行是指从事某项工作时一个步骤一个步骤的去实施,在上一个步骤没有完成的时候是不能开始下一个步骤的,放到GCD里面来说就是想执行的任务需要一个一个来处理,在上一个没有处理完成时,下一个任务需要等待;并行和串行相对,它在一个任务未处理完成时就可以执行另外一个任务,无需等待前面的任务完成;dispatch_sync是将任务添加到指定线程中,当前线程会被阻塞,等待任务在指定线程完成后才会继续往下执行;而dispatch_async在将任务添加到指定线程中得时候不会阻塞当前线程,会继续执行下去。下面用代码来解释这四种方式。

            1、Serial Dispatch Queue+dispatch_sync

    /**
     *  串行+同步(serial+sync)
     */
    - (void)serialSyncQueue {
        dispatch_queue_t queue = dispatch_queue_create("com.hxp.queue", DISPATCH_QUEUE_SERIAL);
        dispatch_sync(queue, ^{
            NSLog(@"%@:queue  serialSyncQueue 0", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"%@:queue  serialSyncQueue 1", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"%@:queue  serialSyncQueue 2", [NSThread currentThread]);
        });
        dispatch_release(queue);
        
        dispatch_queue_t queue1 = dispatch_queue_create("com.hxp.queue", DISPATCH_QUEUE_SERIAL);
        dispatch_sync(queue1, ^{
            NSLog(@"%@:queue1  serialSyncQueue 0", [NSThread currentThread]);
        });
        dispatch_sync(queue1, ^{
            NSLog(@"%@:queue1  serialSyncQueue 1", [NSThread currentThread]);
        });
        dispatch_sync(queue1, ^{
            NSLog(@"%@:queue1  serialSyncQueue 2", [NSThread currentThread]);
        });
        dispatch_release(queue1);
    }

            代码的意思是创建了两个串行的Dispatch Queue:queue和queue1,然后分别在这两个Dispatch Queue中用dispatch_sync添加了三个Block,输出结果如下:

    2015-06-14 09:10:40.296 GCD_Study[16616:607] <NSThread: 0x8c12ed0>{name = (null), num = 1}:queue  serialSyncQueue 0
    2015-06-14 09:10:40.298 GCD_Study[16616:607] <NSThread: 0x8c12ed0>{name = (null), num = 1}:queue  serialSyncQueue 1
    2015-06-14 09:10:40.298 GCD_Study[16616:607] <NSThread: 0x8c12ed0>{name = (null), num = 1}:queue  serialSyncQueue 2
    2015-06-14 09:10:40.299 GCD_Study[16616:607] <NSThread: 0x8c12ed0>{name = (null), num = 1}:queue1  serialSyncQueue 0
    2015-06-14 09:10:40.299 GCD_Study[16616:607] <NSThread: 0x8c12ed0>{name = (null), num = 1}:queue1  serialSyncQueue 1
    2015-06-14 09:10:40.299 GCD_Study[16616:607] <NSThread: 0x8c12ed0>{name = (null), num = 1}:queue1  serialSyncQueue 2

            输出中,num = 1表示当前线程是主线程。通过观察执行顺序可以得知,Serial Dispatch Queue+dispatch_sync:任务是在主线程中按照添加的先后顺序进行执行。

            2、Serial Dispatch Queue+dispatch_async

    /**
     *  串行+异步(serial+async)
     */
    - (void)serialAsyncQueue {
        dispatch_queue_t queue = dispatch_queue_create("com.hxp.queue", DISPATCH_QUEUE_SERIAL);
        dispatch_async(queue, ^{
            NSLog(@"%@:queue  serialAsyncQueue 0", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"%@:queue  serialAsyncQueue 1", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"%@:queue  serialAsyncQueue 2", [NSThread currentThread]);
        });
        dispatch_release(queue);
        
        dispatch_queue_t queue1 = dispatch_queue_create("com.hxp.queue", DISPATCH_QUEUE_SERIAL);
        dispatch_async(queue1, ^{
            NSLog(@"%@:queue1  serialAsyncQueue 0", [NSThread currentThread]);
        });
        dispatch_async(queue1, ^{
            NSLog(@"%@:queue1  serialAsyncQueue 1", [NSThread currentThread]);
        });
        dispatch_async(queue1, ^{
            NSLog(@"%@:queue1  serialAsyncQueue 2", [NSThread currentThread]);
        });
        dispatch_release(queue1);
    }

            同样是创建了两个串行的Dispatch Queue,然后用dispatch_async函数分别往两个Dispatch Queue中添加任务。输出结果如下:

    2015-06-14 09:16:17.131 GCD_Study[16639:1303] <NSThread: 0x8f04d10>{name = (null), num = 2}:queue  serialAsyncQueue 0
    2015-06-14 09:16:17.131 GCD_Study[16639:3103] <NSThread: 0x8e1de20>{name = (null), num = 3}:queue1  serialAsyncQueue 0
    2015-06-14 09:16:17.134 GCD_Study[16639:1303] <NSThread: 0x8f04d10>{name = (null), num = 2}:queue  serialAsyncQueue 1
    2015-06-14 09:16:17.135 GCD_Study[16639:1303] <NSThread: 0x8f04d10>{name = (null), num = 2}:queue  serialAsyncQueue 2
    2015-06-14 09:16:17.135 GCD_Study[16639:3103] <NSThread: 0x8e1de20>{name = (null), num = 3}:queue1  serialAsyncQueue 1
    2015-06-14 09:16:17.136 GCD_Study[16639:3103] <NSThread: 0x8e1de20>{name = (null), num = 3}:queue1  serialAsyncQueue 2

            num = 2,和num = 3 说明新开了两个线程,执行顺序也不是遵循添加的先后顺序了。

            3、Concurrent Dispatch Queue+dispatch_sync

    /**
     *  并行+同步(concurrent+sync)
     */
    - (void)concurrentSyncQueue {
        dispatch_queue_t queue = dispatch_queue_create("com.hxp.queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_sync(queue, ^{
            NSLog(@"%@:queue  concurrentSyncQueue 0", [NSThread currentThread]);
        });
        
        dispatch_sync(queue, ^{
            NSLog(@"%@:queue  concurrentSyncQueue 1", [NSThread currentThread]);
        });
        
        dispatch_sync(queue, ^{
            NSLog(@"%@:queue  concurrentSyncQueue 2", [NSThread currentThread]);
        });
        
        dispatch_release(queue);
        
        dispatch_queue_t queue1 = dispatch_queue_create("com.hxp.queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_sync(queue1, ^{
            NSLog(@"%@:queue1  concurrentSyncQueue 0", [NSThread currentThread]);
        });
        
        dispatch_sync(queue1, ^{
            NSLog(@"%@:queue1  concurrentSyncQueue 1", [NSThread currentThread]);
        });
        
        dispatch_sync(queue1, ^{
            NSLog(@"%@:queue1  concurrentSyncQueue 2", [NSThread currentThread]);
        });
        
        dispatch_release(queue1);
    }

             创建了两个并行的Dispatch Queue,然后用dispatch_sync分别添加Block。因为dispatch_sync是同步添加的,添加的任务处理完成后才可继续往下执行,所以输出结果应该和第一种方式一样:

    2015-06-14 09:21:31.712 GCD_Study[16677:607] <NSThread: 0x8d00080>{name = (null), num = 1}:queue  concurrentSyncQueue 0
    2015-06-14 09:21:31.713 GCD_Study[16677:607] <NSThread: 0x8d00080>{name = (null), num = 1}:queue  concurrentSyncQueue 1
    2015-06-14 09:21:31.714 GCD_Study[16677:607] <NSThread: 0x8d00080>{name = (null), num = 1}:queue  concurrentSyncQueue 2
    2015-06-14 09:21:31.714 GCD_Study[16677:607] <NSThread: 0x8d00080>{name = (null), num = 1}:queue1  concurrentSyncQueue 0
    2015-06-14 09:21:31.715 GCD_Study[16677:607] <NSThread: 0x8d00080>{name = (null), num = 1}:queue1  concurrentSyncQueue 1
    2015-06-14 09:21:31.715 GCD_Study[16677:607] <NSThread: 0x8d00080>{name = (null), num = 1}:queue1  concurrentSyncQueue 2

            尽管添加进得queue是并行的,但是受到添加方式的约束,并不能并行执行。

             4、Concurrent Dispatch Queue+dispatch_async

    /**
     *  并行+异步(concurrent+async)
     */
    - (void)concurrentAsyncQueue {
        dispatch_queue_t queue = dispatch_queue_create("com.hxp.queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
            NSLog(@"%@:queue  concurrentAsyncQueue 0", [NSThread currentThread]);
        });
        
        dispatch_async(queue, ^{
            NSLog(@"%@:queue  concurrentAsyncQueue 1", [NSThread currentThread]);
        });
        
        dispatch_async(queue, ^{
            NSLog(@"%@:queue  concurrentAsyncQueue 2", [NSThread currentThread]);
        });
        dispatch_release(queue);
        
        dispatch_queue_t queue1 = dispatch_queue_create("com.hxp.queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue1, ^{
            NSLog(@"%@:queue1  concurrentAsyncQueue 0", [NSThread currentThread]);
        });
        
        dispatch_async(queue1, ^{
            NSLog(@"%@:queue1  concurrentAsyncQueue 1", [NSThread currentThread]);
        });
        
        dispatch_async(queue1, ^{
            NSLog(@"%@:queue1  concurrentAsyncQueue 2", [NSThread currentThread]);
        });
        dispatch_release(queue1);
    }

            创建了两个并发的Dispatch Queue,然后用异步添加的方式分别给两个queue添加了三个任务。

    输出结果如下:

    2015-06-14 09:28:08.306 GCD_Study[16688:3603] <NSThread: 0x8d214c0>{name = (null), num = 6}:queue1  concurrentAsyncQueue 1
    2015-06-14 09:28:08.305 GCD_Study[16688:1303] <NSThread: 0x8e09850>{name = (null), num = 2}:queue  concurrentAsyncQueue 0
    2015-06-14 09:28:08.305 GCD_Study[16688:3303] <NSThread: 0x8f05c90>{name = (null), num = 4}:queue  concurrentAsyncQueue 2
    2015-06-14 09:28:08.305 GCD_Study[16688:3103] <NSThread: 0x8d21360>{name = (null), num = 3}:queue  concurrentAsyncQueue 1
    2015-06-14 09:28:08.306 GCD_Study[16688:3703] <NSThread: 0x8c4b440>{name = (null), num = 7}:queue1  concurrentAsyncQueue 2
    2015-06-14 09:28:08.305 GCD_Study[16688:3403] <NSThread: 0x8c4b490>{name = (null), num = 5}:queue1  concurrentAsyncQueue 0

            看起来和第二种方式有点类似,第二种方式只创建了两个线程,两个queue因为是串行的,它们在各自的线程中还是按照添加的先后顺序来执行的,而现在这种方式因为queue是并发的,又用的异步方式添加的,所以每个queue中得任务都需要新建一个线程来执行,顺序也没有遵循添加的先后顺序。

  • 相关阅读:
    Symbol Commands
    Control Structures
    script.stub
    Lowest Common Ancestor of a Binary Search Tree
    Move Zeroes
    Odd Even Linked List
    ubuntu18.04系统安装及php7.2,apache2,mysql8,git,svn,composer,vs code 到安装 php 扩展配置php.ini 实现 laravel5.8 运行
    thinkphp3.2.3 自定义路由实践
    thinkphp3.2.3 自动验证 unique 出错的解决办法
    【重磅】中国集成电路产业基金投资版图详解
  • 原文地址:https://www.cnblogs.com/arthas/p/4655205.html
Copyright © 2011-2022 走看看