GCD补充:

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补充:)