美文网首页
GCD补充:

GCD补充:

作者: 富有的心 | 来源:发表于2017-09-06 11:51 被阅读0次

dispatch_after

功能:延迟一段时间把一项任务提交到队列中执行,返回之后就不能取消,常用来在在主队列上延迟执行一项任务。

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> *NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
<#code to be executed after a specified delay#>
});

用法:可以利用dispatch_after写一个自己用的Delay函数,delay一段时间在主线程上执行一段代码

func hwcDelay(delay:Double, closure:()->()) {  
    dispatch_after(  
        dispatch_time(  
            DISPATCH_TIME_NOW,  
            Int64(delay * Double(NSEC_PER_SEC))  
        ),  
        dispatch_get_main_queue(), closure)  
} 
//只需要这样使用
hwcDelay(0.5){
//Do everything you want
}

比如,我们的App需要打开蓝牙,如果在APP启动的时候测到蓝牙是Off状态后,我们应当给用户一个提示打开蓝牙。在view载入完成后,延迟给用户一个提示,也可以给这个提示添加一些动画,要比view在载入完成直接显示提示要友好得多:在viewLoad后,延迟1s,提示一个alertview

class ViewController: UIViewController{      
    func hwcDelay(delay:Double, closure:()->()) {  
    dispatch_after(  
        dispatch_time(  
            DISPATCH_TIME_NOW,  
            Int64(delay * Double(NSEC_PER_SEC))  
        ),  
        dispatch_get_main_queue(), closure)  
}    
    override func viewDidLoad(){      
        super.viewDidLoad()      
        hwcDelay(1.0){  
        var alertview = UIAlertView(title:"Dispatch_after",message:"Message",delegate:self,cancelButtonTitle:"OK")  
        alertview.show()  
    }            
    }      
    override func didReceiveMemoryWarning(){      
        super.didReceiveMemoryWarning()      
    }      
}   

dispatch_apply

功能:把一项任务提交到队列中多次执行,具体是并行执行还是串行执行由队列本身决定(不在意它是并行执行还是串行执行)。注意,dispatch_apply不会立刻返回,在执行完毕后才会返回,是同步的调用。用处:我们调用它可以把不相关的循环提交到后台线程并行执行。

func dispatch_apply(_ iterations: UInt,  
                  _ queue: dispatch_queue_t!,  
                  _ block: ((UInt) -> Void)!) 
//iterations  执行的次数 
//queue       提交到的队列  
//block        执行的任务 

举例:
比如我有一个数组,存储了一系列对象,初始化的时候,这些对象都要调用一次某函数来进行相关的计算。这些计算相互没有影响。这时,我们就可以用dispatch_apply来使用异步队列来初始化。这里把这种情况进行简化

class ViewController: UIViewController{      
    var hwcarray = ["hello","hwc","hellohwc"]  
    override func viewDidLoad(){      
        super.viewDidLoad()      
        dispatch_apply(3,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)){  
        (index:UInt) -> () in  
        var expObject = self.hwcarray[Int(index)] as NSString  
        NSLog("%d",expObject.length)  
    }    
    NSLog("Dispatch_after is over")       
    }      
    override func didReceiveMemoryWarning(){      
        super.didReceiveMemoryWarning()      
    }      
}

可以看到,输出是

3  
5  
8  
dispatch_after is over 

这样写的缺点:
1、会阻塞主线程
2、下文与dispatch_apply的执行结果无关
所以可以在异步队列中调用dispatch_apply,然后执行完成后进行通知。

class ViewController: UIViewController{      
    var hwcarray = ["hello","hwc","hellohwc"]  
    override func viewDidLoad(){   
        super.viewDidLoad()  
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)){  
     dispatch_apply(3,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)){  
        (index:UInt) -> () in  
        var expObject = self.hwcarray[Int(index)] as NSString  
        NSLog("%d",expObject.length)  
     }  
     NSLog("Dispatch_after in global queue is over")    
    }      
         
    NSLog("Dispatch_after in main queue is over")       
    }      
    override func didReceiveMemoryWarning(){      
        super.didReceiveMemoryWarning()      
    }      
}  

这样输出为

8  
Dispatch_after in main queue is over  
3  
5  
Dispatch_after in global queue is over 

可以看到,计算过程相对主队列(主线程)是异步的,在global队列中是并行执行的。

dispatch_group

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

dispatch_queue_t dispatchQueue = dispatch_queue_create("ted.queue.next", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t dispatchGroup = dispatch_group_create();
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
        NSLog(@"dispatch-1");
    });
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
        NSLog(@"dspatch-2");
    });
    dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
        NSLog(@"end");
    });

上面的 log1 和log2输出顺序不定,因为是在并行队列上执行,当并行队列全部执行完成后,最后到main队列上执行一个操作,保证“end”是最后输出。 另外,这里也可以不用创建自己的并行队列,用全局的global,那个也是个并行队列. dispatch_get_gloable_queue(0,0);

dispatch_barrier_async

一个dispatch barrier 允许在一个并发队列中创建一个同步点。当在并发队列中遇到一个barrier, 他会延迟执行barrier的block,等待所有在barrier之前提交的blocks执行结束。 这时,barrier block自己开始执行。 之后, 队列继续正常的执行操作。

dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-1");
    });
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-2");
    });
    dispatch_barrier_async(concurrentQueue, ^(){
        NSLog(@"dispatch-barrier"); 
    });
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-3");
    });
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-4");
    });

dispatch_barrier_async 作用是在并行队列中,等待前面两个操作并行操作完成,这里是并行输出
dispatch-1,dispatch-2,然后执行dispatch_barrier_async中的操作,(现在就只会执行这一个操作)执行完成后,即输出
"dispatch-barrier,最后该并行队列恢复原有执行状态,继续并行执行dispatch-3,dispatch-4

相关文章

  • GCD补充:

    dispatch_after 功能:延迟一段时间把一项任务提交到队列中执行,返回之后就不能取消,常用来在在主队列上...

  • GCD--补充

    最近总是忙着忙那,好久没动过笔了, dispatch_semaphore_create,dispatch_sema...

  • GCD的基本使用(二)

    一.线程间通信 二.GCD常用函数 还需补充.

  • iOS 单例的几种写法

    1、不使用GCD的方式 2、使用GCD // 补充再来说说:Objective-C 里的 Alloc 和Alloc...

  • iOS GCD定时器使用及封装

    上篇文章有说到定时器(NSTimer、CADisplayLink),现在补充上篇遗留的GCD的相关东西 GCD的简...

  • iOS GCD扩展用法

    GCD 延迟执行 GCD 一次性代码 栅栏函数(控制任务的执行顺序) 其他 补充 使用Crearte函数创建的并发...

  • 6.多线程基础( 六)GCD基础

    1.GCD的基本概念 2.GCD代码演示: 1.并发队列+(异步函数) 1.并发队列+(异步函数)的补充: 2.串...

  • 深入理解GCD补充

    先了解几个知识点联合结构我的理解是模板类,具有相同个数成员变量、成员函数的类(成员变量类型不同)union 维护足...

  • 01.什么是RunLoop

    先上一张图,具体的runloop的解读后面再详细补充: 对于runloop的底层,GCD,timer等于runlo...

  • IOS定时器操作和NSTimer的各种坑

    本文列举iOS的各种定时相关操作的使用方法,欢迎大家补充指教。主要包括: NSTimer GCD定时器 dispa...

网友评论

      本文标题:GCD补充:

      本文链接:https://www.haomeiwen.com/subject/kepmjxtx.html