完整详解GCD系列(二)dispatch_after;dispatch_apply;dispatch_once

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

[plain] view plaincopy

  1. func dispatch_after(_ when: dispatch_time_t,
  2. _ queue: dispatch_queue_t!,
  3. _ block: dispatch_block_t!)

参数

[plain] view plaincopy

  1. when 过了多久执行的时间间隔
  2. queue   提交到的队列
  3. block   执行的任务

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

[plain] view plaincopy

  1. func hwcDelay(delay:Double, closure:()->()) {
  2. dispatch_after(
  3. dispatch_time(
  4. DISPATCH_TIME_NOW,
  5. Int64(delay * Double(NSEC_PER_SEC))
  6. ),
  7. dispatch_get_main_queue(), closure)
  8. }

只需要这样使用
hwcDelay(0.5){
//Do everything you want
}
比如,当用户的应用不满足某些我们App需要的条件时候(例如,我们的App需要蓝牙打开),然后在APP启动的时候测到蓝牙Off后,应当给用户一个提
示。在view载入完成后,延迟给用户一个提示,也可以给这个提示添加一些动画,要比view在载入完成直接显示提示要有好的多。
举例
在viewLoad后,延迟1s,提示一个alertview

[plain] view plaincopy

  1. class ViewController: UIViewController{
  2. func hwcDelay(delay:Double, closure:()->()) {
  3. dispatch_after(
  4. dispatch_time(
  5. DISPATCH_TIME_NOW,
  6. Int64(delay * Double(NSEC_PER_SEC))
  7. ),
  8. dispatch_get_main_queue(), closure)
  9. }
  10. override func viewDidLoad(){
  11. super.viewDidLoad()
  12. hwcDelay(1.0){
  13. var alertview = UIAlertView(title:"Dispatch_after",message:"Message",delegate:self,cancelButtonTitle:"OK")
  14. alertview.show()
  15. }
  16. }
  17. override func didReceiveMemoryWarning(){
  18. super.didReceiveMemoryWarning()
  19. }
  20. }

二、dispatch_apply
功能:把一项任务提交到队列中多次执行,具体是并行执行还是串行执行由队列本身决定.注意,dispatch_apply不会立刻返回,在执行完毕后才会返回,是同步的调用。

[plain] view plaincopy

  1. func dispatch_apply(_ iterations: UInt,
  2. _ queue: dispatch_queue_t!,
  3. _ block: ((UInt) -> Void)!)

参数

[plain] view plaincopy

  1. iterations  执行的次数
  2. queue       提交到的队列
  3. block       执行的任务

那么,何时使用这个函数呢?从它的功能不难看出,如果我们可以把不相关的循环提交到后台线程并行执行,并且循环任务调度到后台执行的效率提高,能抵消掉队列调度本身的开销,那么效率会显著提高。

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

[plain] view plaincopy

  1. class ViewController: UIViewController{
  2. var hwcarray = ["hello","hwc","hellohwc"]
  3. override func viewDidLoad(){
  4. super.viewDidLoad()
  5. dispatch_apply(3,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)){
  6. (index:UInt) -> () in
  7. var expObject = self.hwcarray[Int(index)] as NSString
  8. NSLog("%d",expObject.length)
  9. }
  10. NSLog("Dispatch_after is over")
  11. }
  12. override func didReceiveMemoryWarning(){
  13. super.didReceiveMemoryWarning()
  14. }
  15. }

可以看到,输出是

[plain] view plaincopy

  1. 3
  2. 5
  3. 8
  4. dispatch_after is over

由于这样会阻塞主线程,而下文又与dispatch_apply的执行结果无关,所以可以在异步队列中掉dispatch_apply,然后执行完成后进行通知

[plain] view plaincopy

  1. class ViewController: UIViewController{
  2. var hwcarray = ["hello","hwc","hellohwc"]
  3. override func viewDidLoad(){
  4. super.viewDidLoad()
  5. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)){
  6. dispatch_apply(3,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)){
  7. (index:UInt) -> () in
  8. var expObject = self.hwcarray[Int(index)] as NSString
  9. NSLog("%d",expObject.length)
  10. }
  11. NSLog("Dispatch_after in global queue is over")
  12. }
  13. NSLog("Dispatch_after in main queue is over")
  14. }
  15. override func didReceiveMemoryWarning(){
  16. super.didReceiveMemoryWarning()
  17. }
  18. }

这样输出为

[plain] view plaincopy

  1. 8
  2. Dispatch_after in main queue is over
  3. 3
  4. 5
  5. Dispatch_after in global queue is over

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

三、dispatch_once
功能:保证在APP运行期间,block中的代码只执行一次
func dispatch_once(_ predicate: UnsafeMutablePointer<dispatch_once_t>,
                 _ block: dispatch_block_t!)
参数
predicate
用来判断提交的block是否执行完成
block 执行一次的任务
dispatch_once的经典实用场景是单例
单例代码:

[plain] view plaincopy

  1. class hwcSingleton {
  2. var testVariable:Int!
  3. func print(){
  4. testVariable = testVariable + 1
  5. println(testVariable)
  6. }
  7. class var sharedObject: hwcSingleton {
  8. struct StaticStruct {
  9. static var predicate : dispatch_once_t = 0
  10. static var instance : hwcSingleton? = nil
  11. }
  12. dispatch_once(&StaticStruct.predicate) {
  13. StaticStruct.instance = hwcSingleton()
  14. StaticStruct.instance?.testVariable = 10
  15. }
  16. return StaticStruct.instance!
  17. }
  18. }
时间: 2024-10-15 20:09:39

完整详解GCD系列(二)dispatch_after;dispatch_apply;dispatch_once的相关文章

完整详解GCD系列(一)dispatch_async;dispatch_sync;dispatch_

为什么要写这个系列,因为百度了一下,找了很多都是些片面的Blog,拷贝来拷贝去的,写的也很粗糙. 所以,我要写这个系列,尽量把官网文档中GCD的强大功能完整的表达出来.方便自己,也方便别人,如果发现有问题,欢迎提出 本教程的计划:在完整的看过GCD的官方文档之后,我实在想不出来如何用一篇文章详细完整的写出来如此多的功能.所以,决定开一个专栏来写这个教程.计划8篇文章,分别介绍各种功能,每种功能会附上简单完整的示例代码.最后 的一篇文章会进行总结,总结出GCD的经典使用场景.源代码只提供Swift

完整详解GCD系列(一)dispatch_async;dispatch_sync;dispatch_async_f;dispatch_sync_f

为什么要写这个系列,因为百度了一下,找了很多都是些片面的Blog,拷贝来拷贝去的,写的也很粗糙. 所以,我要写这个系列,尽量把官网文档中GCD的强大功能完整的表达出来.方便自己,也方便别人,如果发现有问题,欢迎提出 本教程的计划:在完整的看过GCD的官方文档之后,我实在想不出来如何用一篇文章详细完整的写出来如此多的功能. 所以,决定开一个专栏来写这个教程.计划8篇文章,分别介绍各种功能,每种功能会附上简单完整的示例代码.最后 的一篇文章会进行总结,总结出GCD的经典使用场景.源代码只提供Swif

完整详解GCD系列(四)dispatch_semaphore(信号量)

原创Blog,转载请注明出处 http://blog.csdn.net/hello_hwc?viewmode=contents 一 何为信号量? 简单来说就是控制访问资源的数量,比如系统有两个资源可以被利用,同时有三个线程要访问,只能允许两个线程访问,第三个应当等待资源被释放后再访问. 注意:再GCD中,只有调度的线程在信号量不足的时候才会进入内核态进行线程阻塞 二 如何使用信号量 三个主要函数 创建一个信号量 func dispatch_semaphore_create(_ value: In

完整详解GCD系列(三)-dispatch_group

原创Blog,转载请注明出处 http://blog.csdn.net/column/details/swift-gcd.html 一.dispatch_group 把一组任务提交到队列中,这些队列可以不相关,然后坚挺这组任务完成的事件. 几个用到的函数 1.dispatch_group_create创建一个调度任务组 func dispatch_group_create() -> dispatch_group_t! 2.dispatch_group_async 把一个任务异步提交到任务组里 f

「视频直播技术详解」系列之七:直播云 SDK 性能测试模型

?关于直播的技术文章不少,成体系的不多.我们将用七篇文章,更系统化地介绍当下大热的视频直播各环节的关键技术,帮助视频直播创业者们更全面.深入地了解视频直播技术,更好地技术选型. 本系列文章大纲如下: (一)采集 (二)处理 (三)编码和封装 (四)推流和传输 (五)延迟优化 (六)现代播放器原理 (七)SDK 性能测试模型 本篇是<视频直播技术详解>系列的最后一篇直播云 SDK 性能测试模型,SDK 的性能对最终 App 的影响非常大.SDK 版本迭代快速,每次发布前都要进行系统的测试,测试要

iOS学习之UINavigationController详解与使用(二)页面切换和segmentedController

1.RootView 跳到SecondView 首先我们需要新一个View.新建SecondView,按住Command键然后按N,弹出新建页面,我们新建SecondView 2.为Button 添加点击事件,实现跳转 在RootViewController.xib中和RootViewController.h文件建立连接 在RootViewController.m中实现代码,alloc一个SecondViewController,用pushViewController到navigationCon

shared pool 和buffer pool 详解(之二, Cache Buffers LRU Chain、Cache Buffers LRU Chain闩锁竞争与解决)

[深入解析--eygle]学习笔记 1.1.2  Cache BuffersLRU Chain闩锁竞争与解决 当用户进程需要读数据到Buffer Cache时或Cache Buffer根据LRU算法进行管理等,就不可避免的要扫描LRU  List获取可用Buffer或更改Buffer状态,我们知道,Oracle的Buffer Cache是共享内存,可以为众多并发进程并发访问,所以在搜索的过程中必须获取Latch(Latch是Oracle的一种串行锁机制,用于保护共享内存结构),锁定内存结构,防止

[转]iOS学习之UINavigationController详解与使用(二)页面切换和segmentedController

转载地址:http://blog.csdn.net/totogo2010/article/details/7682433 iOS学习之UINavigationController详解与使用(一)添加UIBarButtonItem是上篇,我们接着讲UINavigationController的重要作用,页面的管理和切换. 1.RootView 跳到SecondView 首先我们需要新一个View.新建SecondView,按住Command键然后按N,弹出新建页面,我们新建SecondView 2

oracle HA 高可用性详解(之二,深入解析TAF,以及HA框架)

oracle HA 高可用性详解(之一,client.server端服务详解):http://write.blog.csdn.net/postedit 我们已经看到TAF是的Oracle的会话能够自动重新连接,需要说明的是,这个能力是基于OCI的,是OCI的一个功能,JDBC Thin Driver无效,因为这种驱动不是构建在OCI库上的. 虽然这个功能发起于RAC,但TAF并不局限于RAC,单实例.DG环境都可以享受这个好处.Oralce声称其TAF能够保证用户会话自动的转移到另一个实例上.这