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中得任务都需要新建一个线程来执行,顺序也没有遵循添加的先后顺序。

posted @ 2015-07-17 17:24  驴车手  阅读(243)  评论(0编辑  收藏  举报