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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容