iOS 进阶学习

GCD

2017-07-03  本文已影响122人  _方丈

目录

知识点
什么是GCD?以下摘自苹果的官方说明
Grand Central Dispatch (GCD)是异步执行任务的技术之一,一般将应用程序中记述的线程管理用的代码在系统级实现。开发者只需要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就能生成必要的线程并计划执行任务。由于线程管理是作为系统的一部分实现的,因此可统一管理,也可执行任务,这样就比以前的线程更有效率。

GCD中有2个核心概念:

1. 任务和队列

2. 并发和并行的区别

(并发和并行的区别:并发是同一时间内执行多个任务,并行是同一时刻执行多个任务!)
* 并发:一个处理器同时处理多个任务。
* 并行:多个处理器或者是多核的处理器同时处理多个不同的任务.

前者是逻辑上的同时发生(simultaneous),而后者是物理上的同时发生.


image.png

3. GCD API 常用场景

Demo

(可直接复制到Xcode中查看)

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self gcdApi];
    
}


-(void)gcdApi{

    [self dispatch_queue];
    
    [self dispatch_set_target_queue];
    
    [self dispatch_group];
    
    [self dispatch_barrier_async];
    
    [self dispatch_apply];

    [self dispatch_suspend__dispatch_resume];
    
    [self dispatchSemaphore];

}



/** 队列
 
 - 1.串行(Serial dispatch、Main dispatch)
 - 2.并行(Concurrent dispatch)
 
 */

#pragma mark - Queue

-(void)dispatch_queue{


    [self serialQueue];
    
    [self concurrentQueue];
    
}

-(void)serialQueue{
    
    /**
     dispatch_queue_create 生成串行队列
     
     - Parameters:
     - value1: 自定义
     - value2: NULL: 默认先进先出(FIFO) 即串行
     */
    dispatch_queue_t mySerial = dispatch_queue_create("com.example.gcd.MySerialQueue", NULL);
    
    /***
     * 异步线程加入串行队列 -> 会开辟新线程 但执行顺序onebyone,有串行队列性质决定
     */
    dispatch_async(mySerial, ^{
        NSLog(@"serialQueue_task1");
    });
    dispatch_async(mySerial, ^{
        NSLog(@"serialQueue_task2");
    });
    
//    dispatch_release(mySerial);
}

-(void)concurrentQueue{
    
    /**
     全局队列,并行
     
     @ Parameters:
         * value1: 优先级 (注意:由于通过XNU内核用于GCD并不能保证时效性,因此执行高优先级只是大致判断并不精准,在处理的执行可有可无下按优先级)
             #define DISPATCH_QUEUE_PRIORITY_HIGH 2
             #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
             #define DISPATCH_QUEUE_PRIORITY_LOW (-2)
             #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
        * value2: 待留参数,传递除0以外的任何值都可能导致一个空返回值
     */
    dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    /***
     * 异步线程加入全局队列 -> 并行
     */
    dispatch_async(global, ^{
        NSLog(@"concurrentQueue_task1");
    });
    dispatch_async(global, ^{
        NSLog(@"concurrentQueue_task2");
    });
}


#pragma mark - dispatch_set_target_queue

-(void)dispatch_set_target_queue{
    
    dispatch_queue_t createSerial = dispatch_queue_create("com.exmple.gcd.targetSerialQueue", NULL);
    
    dispatch_queue_t globelBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    
    /***
     * createSerial 拥有 globelBackground 相同的优先级
     */
    dispatch_set_target_queue(createSerial, globelBackground);
    
}


#pragma mark - dispatch_Group

-(void)dispatch_group{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"blk0");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"blk1");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"blk2");
    });
    
    /**
     * 追加三个Block到globel_queue中,等Block中全部执行完毕,就会执行 dispatch_get_main_queue中的Block
     */
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"Done!");
    });

    //也可以使用wait, DISPATCH_TIME_FOREVER表示一直等待,也可以是一段时间内
//    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
//    NSLog(@"Done!");
    
    //blk0
    //blk1
    //blk2
    //Done!
    
}




#pragma mark - dispatch_barrier_async

-(void)dispatch_barrier_async{
    
    //用dispatch_queue_create函数生成一个Concurrent Dispatch Queue
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrent", DISPATCH_QUEUE_CONCURRENT);
    
    
    dispatch_async(concurrentQueue, ^{
        NSLog(@"blk0_reading");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"blk1_reading");
    });
    
    /**
     * 在blk1结束后,blk2开始前写入,将Block追加到queue中,可以是异步/同步,同步须考虑避免死锁
     */
    dispatch_barrier_async(concurrentQueue, ^{
        NSLog(@"blk_writing");
    });
    
    
    dispatch_async(concurrentQueue, ^{
        NSLog(@"blk2_reading");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"blk3_reading");
    });
    
}


#pragma mark - dispatch_apply

-(void)dispatch_apply{
    
    /**
     * 将Block指定次数的添加到Dispatch queue中,并开辟多个线程
     */
    dispatch_queue_t globel = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_apply(10, globel, ^(size_t index) {
        NSLog(@"%zu",index);
    });
    NSLog(@"done");
    
    //2
    //3
    //6
    //...
    //9
    //done
    
}


#pragma mark - dispatch_suspend__dispatch_resume

-(void)dispatch_suspend__dispatch_resume{
    /**
     * 在大量处理追加到queue中,对已添加过未执行的处理暂停 进行管理开关(挂起/唤醒)
     */
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_suspend(queue);
    //dispatch_resume恢复指定的queue
    dispatch_resume(queue);
}


#pragma mark - dispatchSemaphore

-(void)dispatchSemaphore{
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);//创建信号量初始值为1
    
    NSMutableArray *arry = [[NSMutableArray alloc]init];
    
    for (int i = 0; i<1000; i++) {
        dispatch_async(queue, ^{
       
            //等待semaphore,计数为0时等待
            //一直等待,直到Dispatch_semaphore的计数值>=1减一并执行
            
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//-1,
            /**
             * 由于semphore经wait减一,此时计数值为0,可向下进行
             */
            //访问arry类对象的线程,只有一个,可以安全访问
            [arry addObject:@1];
            
            //onebyone
            dispatch_semaphore_signal(semaphore);//+1
            
    });
}
}

Github地址 : https://github.com/one-tea/GCD-API

参考资料:
grand-central-dispatch-in-depth-part:
https://github.com/nixzhu/dev-blog/blob/master/2014-04-19-grand-central-dispatch-in-depth-part-1.md
http://www.raywenderlich.com/63338/grand-central-dispatch-in-depth-part-2
iOS - 多线程你看全不全:https://juejin.im/entry/57dcc1cc0bd1d00057e97dc7
IOS多线程之GCD的执行原理:http://www.jianshu.com/p/5840523fb3ea

上一篇 下一篇

猜你喜欢

热点阅读