iOS多线程编程篇:XNU内核级之Grand Central Dispatch(GCD)

GCD实现多线程的方式:不需要程序员去创建和管理线程,只需创建一个调度队列Dispatch Queue,将Block事件添加到这个队列即可。

一种内核级实现并发编程方式,能够高效地“窃取”多核CPU性能。

Dispatch Queue

dispatch_time_t getData(NSDate *date){

    NSTimeInterval interval;
    double second, subsecond;
    struct timespec time;
    dispatch_time_t miletone;

    interval = [date timeIntervalSince1970];
    subsecond = modf(interval, &second);
    time.tv_sec = second;
    time.tv_nsec = subsecond * NSEC_PER_SEC;
    miletone = dispatch_walltime(&time, 0);

    return miletone;
}
//创建队列
    //串行队列  第一个参数,指定串行队列的名称,第二个参数为NULL的话就是串行的
    dispatch_queue_t seriQueue = dispatch_queue_create("com.test", NULL);

    dispatch_async(seriQueue, ^{



    });

    //并行队列  第一个参数还是队列名称   第二参数为并行
    dispatch_queue_t conQueue = dispatch_queue_create("com.con", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(conQueue, ^{



    });

    //获取系统提供的队列
    dispatch_queue_t mainQueue = dispatch_get_main_queue();

    dispatch_queue_t lowQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);

    dispatch_queue_t highQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

    dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_queue_t backQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

        //访问和读取数据库操作
    //注意:这里的并行队列只能使用自定义的并行队列才能达到如下需求
    //1、2、3、4无序输出  接着输出5  然后6、7、8、9无序输出
    dispatch_async(conQueue, ^{

        NSLog(@"=1");
    });
    dispatch_async(conQueue, ^{

        NSLog(@"=2");
    });
    dispatch_async(conQueue, ^{

        NSLog(@"=3");
    });
    dispatch_async(conQueue, ^{

        NSLog(@"=4");
    });

    dispatch_barrier_async(conQueue, ^{

        NSLog(@"=5");
    });

    dispatch_async(conQueue, ^{

        NSLog(@"=6");
    });
    dispatch_async(conQueue, ^{

        NSLog(@"=7");
    });
    dispatch_async(conQueue, ^{

        NSLog(@"=8");
    });
    dispatch_async(conQueue, ^{

        NSLog(@"=9");
    });    

    //seriQueue 要变更的队列
    //mainQueue 按这个队列的优先级执行
    dispatch_set_target_queue(seriQueue, mainQueue);

    //延迟做某事
    //第一种方式  60s 后
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{


    });

    //第二种方式 60ms 后
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 60ull * NSEC_PER_MSEC);

    dispatch_after(time, mainQueue, ^{

    });

    //传入一个日期,定时这个日期下操作某事(闹钟功能)
    dispatch_after(getData([NSDate new]), mainQueue, ^{



    });


    //创建队列组
    dispatch_group_t group = dispatch_group_create();

    dispatch_group_async(group, defaultQueue, ^{

    });
    dispatch_group_async(group, defaultQueue, ^{

    });
    dispatch_group_async(group, defaultQueue, ^{

    });

    dispatch_group_notify(group, defaultQueue, ^{

    });


    long result = dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    if (result == 0) {

        //所有的线程执行完毕
    } else {

        //仍有线程在运行。
    }

    long result1 = dispatch_group_wait(group, DISPATCH_TIME_NOW);

    dispatch_async(defaultQueue, ^{

        //可作为数组的循环
        dispatch_apply(10, highQueue, ^(size_t index) {

            NSLog(@"%zu", index);
            if (index == 5) {

                //暂停队列
                dispatch_suspend(highQueue);
            }
        });

        NSLog(@"结束");

        //恢复队列
        dispatch_resume(highQueue);

    });


    //信号量创建  dispatch semaphore 是持有计数的信号,该计数是多线程编程中的计数类型信号。所谓信号,类似于过马路时常用的手旗。可以通过时举起手旗,不可通过时放下手旗。而在dispatch semaphore中,使用计数来实现该功能。计数为0时等待,计数为1或大于1时,减去1而不等待
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

    dispatch_semaphore_signal(semaphore);  //让信号量加1

    long esult = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //如果信号量大于或等于1,不等待且减1

    if (esult == 0) {

        NSLog(@"完成");
    }

    NSMutableArray *array = [NSMutableArray array];

    dispatch_semaphore_t sem = dispatch_semaphore_create(1);  //信号量等于1

    dispatch_async(defaultQueue, ^{

       dispatch_apply(10, defaultQueue, ^(size_t index1) {

           dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);  //信号量减1

           NSLog(@"====%zu", index1);
           [array addObject:@"1"];

           dispatch_semaphore_signal(sem);   //信号量加1

       });

        dispatch_async(mainQueue, ^{

            NSLog(@"====%lu", (unsigned long)array.count);
        });

    });

Dispatch Source

它是BSD系内核惯有功能kqueue的包装。其CPU负荷非常小,尽量不占用资源。

//dispatch source 可处理以下事件:
    DISPATCH_SOURCE_TYPE_TIMER;      //定时器
    DISPATCH_SOURCE_TYPE_WRITE;      //可读取文件映像
    DISPATCH_SOURCE_TYPE_DATA_ADD;   //变量增加
    DISPATCH_SOURCE_TYPE_DATA_OR;    //变量OR
    DISPATCH_SOURCE_TYPE_MACH_SEND;  //MACH 端口发送
    DISPATCH_SOURCE_TYPE_MACH_RECV;  //MACH 端口接收
    DISPATCH_SOURCE_TYPE_PROC;       //检测到与进程相关的事件
    DISPATCH_SOURCE_TYPE_SIGNAL;     //接收信号
    DISPATCH_SOURCE_TYPE_VNODE;      //文件系统有变更
    DISPATCH_SOURCE_TYPE_WRITE;      //可写入文件映像

    //在定时器经过指定时间时设置main queue 为追加处理的dispatch Queue
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());

    /**

      将定时器设定为15秒后   (立即执行:设置为 dispatch_walltime(NULL, 0))
      不指定重复(每秒重复做某事可设置为 1.0*NSEC_PER_SEC )
      允许迟延1秒

     */
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 15 * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, 1*NSEC_PER_SEC);

    //指定定时器指定时间内执行的处理
    dispatch_source_set_event_handler(timer, ^{

        NSLog(@"执行这句代码");
        //取消dispatch source
        dispatch_source_cancel(timer);

    });

    dispatch_source_set_cancel_handler(timer, ^{

        NSLog(@"取消处理");

    });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sailip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值