iOS多线程编程GCD

1.GCD简介

GCD(Grand Central Dispatch)是系统基于C封装的多线程编程技术。它会自动管理线程的生命周期(创建线程、调度任务、销毁线程)。结合block使用,方便灵活。因为GCD偏向系统低层。所以使用GCD,多线程编程的效率会更高。而且使用起来也很方便,系统都为我们封装好了。

导入库?

使用GCD不需要手动导入任何框架。GCD使用的是一个系统库libdispatch,因为系统代码也在使用这个库,所以不需要我们导入。

2.创建与获取队列

1.串行和并发

串行:意思就是一串一串的执行,队列中的任务一个一个的执行,只需要创建一个线程就够了。
并发:队列中的任务是并发执行的,也就是一起执行的,所以需要创建多个线程执行任务。

2.串行队列

创建串行队列

   // 串行队列  参数:1.唯一标识符 2.NULL和DISPATCH_QUEUE_SERIAL都表示串行队列
    dispatch_queue_t serial_queue =  dispatch_queue_create("com.xiaoleilei.serial_queue", DISPATCH_QUEUE_SERIAL);

3.并发队列

创建并发队列

   // 并发队列  参数:1.唯一标识符 2.DISPATCH_QUEUE_CONCURRENT
    dispatch_queue_t concurrent_queue =  dispatch_queue_create("com.xiaoleilei.concurrent_queue",  DISPATCH_QUEUE_CONCURRENT);

4.全局队列

全局队列是在全局都可以获取的一个并发队列,不需要创建,只需要获取就行了,全局队列有四中,按优先级不同获取。

  • DISPATCH_QUEUE_PRIORITY_HIGH
  • DISPATCH_QUEUE_PRIORITY_DEFAULT
  • DISPATCH_QUEUE_PRIORITY_LOW
  • DISPATCH_QUEUE_PRIORITY_BACKGROUND

获取全局队列

  // 全局队列(并发队列)参数:1.优先级 2.填0
    dispatch_queue_t global_queue =  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

5.主队列

主队列是一个在全局都可以获取的串行队列,该队列中的任务是在主线程中执行的。一般会将一些在主线程中执行的任务加到主队列中。

获取主队列

  // 主队列 (串行队列)
    dispatch_queue_t main_queue =  dispatch_get_main_queue();

3.提交任务

1.同步提交

dispatch_sync同步添加任务到队列中

  // 同步提交 参数1:创建的队列 参数2:block{执行的任务}
    dispatch_sync(serial_queue, ^{
    //任务
    });

注意: 同步提交不管提交到什么队列,不会开辟新线程,在当前线程中执行。同步提交任务到当前队列 会造成线程死锁。

    dispatch_sync(main_queue, ^{
        NSLog(@"任务执行中。。。。");
    });
    NSLog(@"同步提交完成");

    // 1.dispatch_sync完成后会执行输出
    // 2.dispatch_sync要等待block完成后才能继续执行 此时主线程被阻塞
    // 3.执行block中的任务,要在主线程中执行
    // 主线程在做同步提交任务 并且等待提交的block任务完成
    // block中任务的执行应该在主线程执行,主线程在等待提交的任务完成才能执行block中的任务

2.异步提交

dispatch_async异步添加任务到队列中

//参数1:创建的队列 参数2:block{执行的任务}
   dispatch_async(serial_queue, ^{
        NSLog(@"异步提交");
    });

4.监测队列中任务执行完成

如果想在队列中所有的任务执行完成后再做某种操作,在串行队列中,可以把该操作放到最后一个任务执行,但是在并行队列中怎么做呢?这就有dispatch_group成组操作。

   // 监测并发队列中任务执行完成
    NSLog(@"dispatch_group");
    //获取全局队列,全局队列是并发队列
    dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 创建group
    dispatch_group_t group = dispatch_group_create();
    // 向group中添加任务
    dispatch_group_async(group, global_queue, ^{
         NSLog(@"任务1正在执行。。。。");
    //让线程睡5秒钟,模拟正在执行任务
        [NSThread sleepForTimeInterval:5];
    });
    dispatch_group_async(group, global_queue, ^{
          NSLog(@"任务2正在执行。。。。");
      //让线程睡5秒钟,模拟正在执行任务
        [NSThread sleepForTimeInterval:5];
    });
    // 队列中的任务完成后通知
    dispatch_group_notify(group, global_queue, ^{
        NSLog(@"事情干完了");
    });

执行结果

5.线程间的通信(信号量)

GCD中有3个信号量有关的操作:
dispatch_semaphore_create     信号量创建
dispatch_semaphore_wait     信号量等待 wait会阻塞线程并且检测信号量的值,直到信号量值大于0才会开始往下执行,同时对信号量执行-1操作.
dispatch_semaphore_signal    发送通知 +1 如果+1前信号量值小于0直接唤醒线程继续执行
模拟场景:控制并发队列中并发数量为5.

    NSLog(@"dispatch_semaphore");
    //创建一个并发队列
    dispatch_queue_t concurrent_queue = dispatch_queue_create("com.xiaoleilei.semaphore", DISPATCH_QUEUE_CONCURRENT);
    //创建信号量 参数为5
    dispatch_semaphore_t sema = dispatch_semaphore_create(5);
    //提交一百个任务。让他们五个五个的并发
    for (int i=0; i<100; i++)
    {
        dispatch_async(concurrent_queue, ^{
               // 等待  wait会阻塞线程并且检测信号量的值,直到信号量值大于0才会开始往下执行,同时对信号量执行-1操作.
            dispatch_semaphore_wait(sema,  DISPATCH_TIME_FOREVER);

            NSLog(@"第%d个任务执行",i);
            //模拟任务执行了五秒
            [NSThread sleepForTimeInterval:5];
             // 发送通知 +1 如果+1前的值信号量值小于0直接唤醒线程继续执行
            dispatch_semaphore_signal(sema);
        });
    }

运行结果

画了一个图(字有点丑TooT):

这里写图片描述

6.dispatch_once

dispatch_once 是用来保证某个代码块在整个程序生命周期只执行一次。可以用来完成单例类的实现。

  [self testDispatchOnce];
    [self testDispatchOnce];
    [self testDispatchOnce];
    [self testDispatchOnce];
    [self testDispatchOnce];
    [self testDispatchOnce];
    [self testDispatchOnce];
- (void)testDispatchOnce
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"testDispatchOnce");
    });
}

运行结果:
这里写图片描述

7.dispatch_barrier_async

在并发队列中,使用dispatch_barrier_async添加的任务,在执行此任务时,队列中的其他任务不执行,当此任务执行完毕后,队列中的其他任务才开始执行。
相当于,食堂有四个窗口打饭,我往那一站,四个窗口都为我打饭,等我把饭打完了,其他人才接着打饭。
注意:要使用自己创建的并发队列,如果使用系统的并发队列的话,是没有效果的。用起来就相当于dispatch_async(异步提交)。

//创建一个并行队列
 dispatch_queue_t concurrent_queue_barrier = dispatch_queue_create("com.xiaoleilei.barrier", DISPATCH_QUEUE_CONCURRENT);
//提交任务1
    dispatch_async(concurrent_queue_barrier, ^{
        NSLog(@"任务1开始执行啦");
        [NSThread sleepForTimeInterval:5];
        NSLog(@"任务1执行完啦");
    });
  //提交任务2  
    dispatch_async(concurrent_queue_barrier, ^{
        NSLog(@"任务2开始啦");
        [NSThread sleepForTimeInterval:5];
        NSLog(@"任务2执行完啦");
    });
    // dispatch_barrier_async
    //插队
    dispatch_barrier_async(concurrent_queue_barrier, ^{
        NSLog(@"插队的任务3开始执行啦");
        [NSThread sleepForTimeInterval:10];
        NSLog(@"插队的任务3执行完啦");
    })
    //提交任务4
    dispatch_async(concurrent_queue_barrier, ^{
        NSLog(@"任务4开始执行啦");
        [NSThread sleepForTimeInterval:5];
        NSLog(@"任务4执行完啦");
    });
    //提交任务5
    dispatch_async(concurrent_queue_barrier, ^{
        NSLog(@"任务5开始执行啦");
        [NSThread sleepForTimeInterval:5];
        NSLog(@"任务5执行完了");
    });

运行结果:
这里写图片描述

7.dispatch_apply

dispatch_apply的功能是,将任务指定次数添加到并发队列中。
dispatch_apply是同步的,他会阻塞当前线程,知道队列中的循环任务执行完毕。

 //创建并发队列
    dispatch_queue_t concurrent_queue_apply = dispatch_queue_create("com.xiaoleilei.apply", DISPATCH_QUEUE_CONCURRENT);
//将指定次数的任务添加到队列中
//参数1.循环次数 参数2.队列  size_t后面的参数是循环次数(无符长整型)
    dispatch_apply(10, concurrent_queue_apply, ^(size_t idx) {
        NSLog(@"任务执行第%ld", idx);
        [NSThread sleepForTimeInterval:5];
        NSLog(@"%@", [NSThread currentThread]);
        NSLog(@"任务执行第%ld完毕-----", idx);
    });
    //当任务的循环次数执行完毕才唤醒当前线程。
    NSLog(@"所有循环任务执行完毕");

运行结果:
这里写图片描述

8.dispatch_after&&dispatch_time

dispatch_after&&dispatch_time实现延迟函数

 // 构建一个时间 参数1.什么时候 参数2.增量
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC));

    NSLog(@"开始");
    // 实现延迟函数
    dispatch_after(time, dispatch_get_main_queue(), ^{
        NSLog(@"延迟10秒");
    });

运行结果:
这里写图片描述

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值