zoukankan      html  css  js  c++  java
  • OC多线程之GCD ----- 2

    dispatch_create生成的Queue不管是并行队列还是串行队列,其优先级都是默认优先级

    但是可以用dispatch_set_target_queue来改变队列的优先级

    dispatch_set_target_queue(原来的队列, 目标优先级队列)

    使用这个函数需要获取两个队列,一个是需要变更优先级的队列,一个是指定优先级的队列(指定优先级的队列可以通过get_global获得)

    如果多个串行队列优先级相同,那么这些队列里的任务也会串行执行

    dispatch_after函数并不能非常精确的在一段时间后执行任务,dispatch_after只是在指定时间后将block插入到队列中,至于什么时候执行要看系统的执行状况

    延迟多少触发大家都知道,下面这个代码是利用NSDate生成一个时间,让dispatch在这个时间去执行block,但是这个貌似只能精确到分,没有精确到秒,可能是我代码有问题,原因还早查找中

    @implementation NSDate (dis)
    
    -(dispatch_time_t)getDis{
        
        
        
        NSTimeInterval interval;
        double second,subsecond;
        struct timespec time;
        dispatch_time_t milestone;
        
        
        interval = [self timeIntervalSince1970];
        subsecond = modf(interval, &second);
        
        time.tv_sec = second;
        time.tv_nsec = subsecond * NSEC_PER_SEC;
        milestone = dispatch_walltime(&time, 0);
        
        return milestone;
    }
    
    @end

    GCD使用过程中应该谨慎使用sync函数,因为稍有不慎就将导致死锁

    dispatch_apply函数是asyn和group的关联API,该函数可以执行指定次数的block 但是会阻塞线程(同步执行),见下面的代码

     
        dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
            NSLog(@"%zu",index);
        });
        
        NSLog(@"done");

    //===============打印结果

    2014-06-19 20:58:55.097 efvervq[5840:60b] 0

    2014-06-19 20:58:55.097 efvervq[5840:1303] 1

    2014-06-19 20:58:55.097 efvervq[5840:3803] 2

    2014-06-19 20:58:55.099 efvervq[5840:60b] 4

    2014-06-19 20:58:55.097 efvervq[5840:3903] 3

    2014-06-19 20:58:55.099 efvervq[5840:1303] 5

    2014-06-19 20:58:55.099 efvervq[5840:3803] 6

    2014-06-19 20:58:55.099 efvervq[5840:60b] 7

    2014-06-19 20:58:55.101 efvervq[5840:3803] 9

    2014-06-19 20:58:55.099 efvervq[5840:3903] 8

    2014-06-19 20:58:55.102 efvervq[5840:60b] done



    //=================

    顺序不一,但是在函数外面的done是最后打印的

    PS.但是不要搞混了.使用并行队列和sync函数连续添加block时打印出来的书序是0123456789的

    我们可以在async函数中使用apply函数,这样能避免阻塞主队列

    dispatch_suspend(queue)可以将队列挂起,

    dispatch_resume(queue)可以恢复指定的queue,然后系统会继续执行未处理的操作,对已经执行的没有影响

    有时需要十分精准的数据安全控制,那么使用dispatch_semaphore可以提供比SerialQueue更加细小颗粒度的访问控制,因为这个是通过信号量控制的

    但信号量<0时时不允许访问的

    看下面的代码

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        /**
         *  生成dispatch_semaphore
         
         *  将其计数初始值设为1
         
         *  保证可访问NSMutableArray类对象的线程同时只能有一个
         */
        
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
        
        
        NSMutableArray *array = [NSMutableArray array];
        
        for (int i = 0; i < 10000; i++) {
            
            dispatch_async(queue, ^{
                /**
                 *  等待 dispatch_semaphore
                 *
                 *  一直等待,知道semaphore数值大于等于1
                 */
                
                dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
                /**
                 *  执行到此,信号量为1 然后系统自动减去1,变为0
                 * 此时只有执行到这的线程访问array
                 */
                [array addObject:[NSNumber numberWithInt:i]];
                
                /**
                 *  访问结束后,给信号量+1.以便其他的线程继续像array中添加对象
                 */
                
                dispatch_semaphore_signal(semaphore);
                
            });
            
        }

    GCD除了队列之外还有dispatch_source,这个功能可以以相当低的资源消耗来处理文件读写,定时器,信号接收等事件,更多功能可以去查阅苹果的文档

    /**
         *  创建一个source  
         DISPATCH_SOURCE_TYPE_TIMER 为source的类型(定时器)
         */
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
        
        
        /**
         *  设置时间
         *  延迟15秒后
        
         * 每2秒重复一次
         *允许延迟1秒
         */
        dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 15ull * NSEC_PER_SEC), 2ull * NSEC_PER_SEC, 1ull * NSEC_PER_SEC);
        
        // 执行的任务
        
       __block int a = 0;
        
        dispatch_source_set_event_handler(timer, ^{
            NSLog(@"wake up");
            a++;
            if (a == 8) {
                dispatch_source_cancel(timer);
                
            }
        });
        
        //取消时的操作
        dispatch_source_set_cancel_handler(timer, ^{
            NSLog(@"cancled");
        });
        
        
        /**
         *  如果是MRC 需要dispatch_release
         */
        
        
        //开始工作
        dispatch_resume(timer);
        

    如果你想不让timer重复执行,可以将重复时间设为dispatch_timeForever 或者在set_event_handler里面执行完毕以后cancle掉

    set_event_handler里面必须有cancel(或者里面执行的方法有cancel,就是可以搜寻到),否则timer不会执行,你可以自己试试

    但是你可以用if(0){cancel}来骗过系统,但是一定不要忘记cancel

  • 相关阅读:
    react 安装脚手架过程
    微信小程序-分享功能
    echarts 实现多图联动显示tooltip
    dom 相同父节点查找
    js 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果
    vue手写el-form组件
    vue组件传值、通信
    vue项目打包桌面应用 exe程序 以及打包为安装程序exe
    vue 使用echarts来制作图表
    前端数据可视化插件-图表
  • 原文地址:https://www.cnblogs.com/xyzaijing/p/3903521.html
Copyright © 2011-2022 走看看