• iOS多线程-GCD之常用函数


    • 延迟执行任务函数dispatch_after(.....)

        -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        NSLog(@"start");
        //dispatch_after 是异步执行的
        //队列只决定在哪个线程中执行任务 并不能决定执行时间
        /**
         * 第一个参数: 在哪个时间点执行
         *            dispatch_time(从哪个时间点开始,经历多少纳秒)
         * 第二个参数: 在哪个队列中执行block任务
         * 第三个参数: block任务
         */
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"%@",[NSThread currentThread]);
        });
        NSLog(@"end");
      }




    原文链接:http://www.jianshu.com/p/4e46b4e0eb65

    • 一次性执行dispatch_once(...)

       -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        //一次性执行的机制,能保证在程序启动后只会执行一次,并且是线程安全的,在主线程中执行
        //一般使用dispatch_once来做一次性执行,效率高, 在单例模式中使用.
        //可以利用互斥锁在实现此功能,但不建议使用,因为效率非常低!!!!
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            NSLog(@"");
        });
      }
    • 栅栏函数dispatch_barrier_async/dispatch_barrier_sync

      -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
      
       dispatch_queue_t queue = dispatch_queue_create("yuxuan", DISPATCH_QUEUE_CONCURRENT);
      
       dispatch_async(queue, ^{
           NSLog(@"任务1");
       });
      
        dispatch_async(queue, ^{
           NSLog(@"任务2");
        });
      
        //栅栏函数(同步函数就没必要控制顺序了,因为它是有序的)
                //dispatch_barrier_async 是异步函数不会阻塞线程
                //dispatch_barrier_sync 是同步函数 会阻塞线程
        //如果所有任务都在同一个并行队列中,并且这个并行队列不是系统自带全局并行队列
        //哪么在barrier之前添加的方法会先被执行,只有等barrier之前的任务执行完毕后才会执行barrier任务
        //只有barrier任务执行完毕后,才会执行后添加的任务
        dispatch_barrier_async(queue, ^{
            NSLog(@"我是个可爱的路障");
        });
      
        dispatch_async(queue, ^{
           NSLog(@"任务3");
        });
      
        dispatch_async(queue, ^{
           NSLog(@"任务4");
        });
      
        NSLog(@"end");
      }
    • 队列组的使用dispatch_group_t

      • 方式一:

        -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        
        //创建一个队列组
        dispatch_group_t group = dispatch_group_create();
        
        //创建两个不同的队列来测试
        dispatch_queue_t queue1 = dispatch_get_global_queue(0, 0);
        
        dispatch_queue_t queue2 = dispatch_queue_create("yuxuan", DISPATCH_QUEUE_CONCURRENT);
        
        //dispatch_group_async 异步函数
        //系统会先把任务放入队列中,然后把队列放入组中
        //从组中把队列取出来,在从队列里取任务执行
        dispatch_group_async(group, queue1, ^{
        [NSThread sleepForTimeInterval:1.0];
          NSLog(@"download 1");
        });
        
        dispatch_group_async(group, queue2, ^{
          [NSThread sleepForTimeInterval:1.0];
          NSLog(@"download 2");
        });
        //给group添加一个通知,异步函数
        //当group队列中所有任务执行完毕,就会通知group执行block
        /*
        * 第一个参数: 为那个队列组添加通知
        * 第二个参数: 决定block在什么线程中执行
        * 第三个参数: block 代码块
        */
        dispatch_group_notify(group, dispatch_queue_create("yuxuan1",DISPATCH_QUEUE_CONCURRENT), ^{
          NSLog(@"OK");
        });
        NSLog(@"end");
        }
      • 方式二:

        -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        /*
        dispatch_group_async底层实现:
        void dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block)
        {
           dispatch_retain(group);
           dispatch_group_enter(group);
           dispatch_async(queue, ^{
               block();
               dispatch_group_leave(group);
               dispatch_release(group);
           });
        }
        */
        dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
        
        //创建一个队列组
        dispatch_group_t group =  dispatch_group_create();
        
        //通知队列组进入队列组
        dispatch_group_enter(group);
        
        dispatch_async(queue, ^{
          NSLog(@"111");
          //任务执行完毕
          //通知队列组离开队列组
          dispatch_group_leave(group);
        });
        
        //通知队列组进入队列组
        dispatch_group_enter(group);
        
        dispatch_async(queue, ^{
          NSLog(@"222");
          //任务执行完毕
          //通知队列组离开队列组
          dispatch_group_leave(group);
        });
        
        //等待所有任务执行完毕,一直等待.会阻塞线程
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
        
        //    dispatch_group_notify(group, queue, ^{
        //        NSLog(@"over");
        //    });
        }
    • GCD定时器

      -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
       //创建一个队列,创建GCD定时器时使用
        dispatch_queue_t queue = dispatch_queue_create("yuxuan", DISPATCH_QUEUE_SERIAL);
        //创建一个GCD定时器(触发器)
        //第四个参数:传入一个队列,决定了定时器回调任务执行方式.
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        //dispatch_source_t其实本质是一个类,由于是局部变量,方法执行完,就会被释放.
        self.timer = timer;
        //设置定时器
        /*
         第一个参数:给那个定时器设置
         第二个参数:什么时候启动
         第三个参数:间隔多久执行一次
         第四个参数:设置精准度:0 代表最高精准(尽量让定时器精准), 大于0的的话代表是在多少秒内接受.
         第四个参数存在意义:主要是为了提高程序性能, 设置越大,能减轻CPU的压力
         注意:GCD定时器传入的时间都是纳秒
         */
        dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.0 * NSEC_PER_SEC);
         //第一个参数:给那个定时器设置
        //第二个参数:设置定时器回调block
        //异步执行的,具有创建新线程的能力
        //具体是否创建线程,创建几条线程是由定时任务创建时,传入的queue决定的
        dispatch_source_set_event_handler(timer, ^{
            NSLog(@"%@",[NSThread currentThread]);
        });
            //启动定时器
        dispatch_resume(timer);
      }
  • 相关阅读:
    AcWing 1027. 方格取数 dp
    AcWing 1014. 登山 dp
    acwing 482. 合唱队形 dp
    LeetCode 1463. 摘樱桃II dp
    LeetCode 100. 相同的树 树的遍历
    LeetCode 336. 回文对 哈希
    LeetCode 815. 公交路线 最短路 哈希
    算法问题实战策略 DARPA大挑战 二分
    算法问题实战策略 LUNCHBOX 贪心
    AcWing 1100. 抓住那头牛 BFS
  • 原文地址:https://www.cnblogs.com/it-k-50/p/6117451.html
Copyright © 2020-2023  润新知