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