学习总结-GDC

2018-07-09  本文已影响0人  赤脚青春_922d

多线程(GCD)

一.实现方式

二.生命周期(五种状态)

状态图

三.多线程安全问题

原因: 多个线程同时访问一个资源所引起的数据错乱问题

解决方案
@synchronized(锁对象(一般用self)) {
    // 需要锁定的代码
}

关于GCD

1: GCD特点

2: GCD的基本概念

3: 队列的创建方法

dispatch_queue_t queue = dispatch_queue_create(const char * _Nullable label,  
dispatch_queue_attr_t  _Nullable attr)

参数说明:第一个为标识符,可不传;第二个参数为队列类型(并发队列DISPATCH_QUEUE_CONCURRENT,穿行队列DISPATCH_QUEUE_SERIAL);
此外还有两种创建队列的方法

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);//获取全局并发队列
dispatch_queue_t queue = dispatch_get_main_queue();//获取主队列

4: 任务的创建方式

    dispatch_sync(dispatch_get_global_queue(0, 0), ^{// 同步执行任务
        NSLog(@"我是同步执行的任务");
    });
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{// 异步执行任务
        NSLog(@"我是异步执行的任务");
    });

5: GCD的使用
组合方式:有六种组合方式(串行/并发/主队列 ✖️同步/异步)

  1. 串行同步
  2. 串行异步
  3. 并发同步
  4. 并发异步
  5. 主队列同步
  6. 主队列异步

同步/异步决定是否开新线程,串行/并发/主队列决定是否按顺序执行任务
特别说明:5.主队列同步,会发生死锁,程序奔溃

- (void)testSync {
    dispatch_sync(dispatch_get_main_queue(), ^{
        //需要执行的任务
    });
}

原因:在主线程中使用同步对于任务是立刻执行的,即:block中的任务会立刻执行,但是此时主线程正在处理testSync()方法,所以任务就需要等待testSync()执行后才能执行,但是该任务就处于testSync()方法中,所以就造成无限等待中也就是死锁

GCD实用API

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)),dispatch_get_main_queue(), ^{
        //3秒后需要做的事情
    });
dispatch_queue_t asyncQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(asyncQueue, ^{
        for (NSUInteger i = 0; i < 10; i++) {
            NSLog(@"11111--%zd--%@",i,[NSThread currentThread]);
        }
    });
    dispatch_async(asyncQueue, ^{
        for (NSUInteger i = 0; i < 10; i++) {
            NSLog(@"2222--%zd--%@",i,[NSThread currentThread]);
        }
    });
    dispatch_barrier_async(asyncQueue, ^{
        NSLog(@"我在这里把他拦截下来");
    });
    
    dispatch_async(asyncQueue, ^{
        for (NSUInteger i = 0; i < 10; i++) {
            NSLog(@"33333--%zd--%@",i,[NSThread currentThread]);
        }
    });
    dispatch_async(asyncQueue, ^{
        for (NSUInteger i = 0; i < 10; i++) {
            NSLog(@"44444--%zd--%@",i,[NSThread currentThread]);
        }
    });

根据log可以发现,'3','4' 都会再'1','2'执行完之后才会执行。这样就达到了栅栏的效果。
注意: 栅栏函数不能使用全局并发队列, 必须是自己通过函数创建的并发队列,否则将达不到栅栏效果

CFTimeInterval startTime = CFAbsoluteTimeGetCurrent();
//    for (int i = 0; i < 10000; i ++) {
//        NSLog(@"");
//    }//2.395429
    dispatch_queue_t concurrentQ = dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT);
    dispatch_apply(10000, concurrentQ, ^(size_t i) {
        NSLog(@"");
    });//2.40
    CFTimeInterval endTime = CFAbsoluteTimeGetCurrent();
    NSLog(@"%f",endTime-startTime);

可能是我在循环中没有做什么操作吧,for循环竟然更快dispatch_applydispatch_sync函数和dispatch_group的关联API

    dispatch_group_t group =  dispatch_group_create();//队列组创建
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"有一个任务完成!");
    });
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"有一个任务完成!");
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"前面两个任务执行完毕,更新UI");
    });
上一篇 下一篇

猜你喜欢

热点阅读