ios多线程操作(七)—— GCD延迟操作与一次性代码

来源:互联网 发布:怎么认识外国妹子软件 编辑:程序博客网 时间:2024/05/22 15:51
使用GCD函数可以进行延时操作,该函数为
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{  
  2.     });  


  现在我们来分解一下参数
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds *NSEC_PER_SEC)) :
NSEC_PER_SEC在头文件中的定义如下:
#define NSEC_PER_SEC 1000000000ull /* nanoseconds per second */
该参数表示从现在开始经过多少纳秒
dispatch_get_main_queue():表示主队列
^{
    }:表示一个block任务。
   我们可以来测试一下经过多少纳秒之后,由主队列调度任务是异步执行还是同步执行,代码如下:
 
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //  when 时间 从现在开始经过多少纳秒  
  2.    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));  
  3.     
  4.    void (^task)() = ^ {  
  5.        // 延迟操作执行的代码  
  6.        NSLog(@"%@", [NSThread currentThread]);  
  7.    };   
  8.    // 经过多少纳秒,由主队列调度任务异步执行  
  9.    dispatch_after(when, dispatch_get_main_queue(), task);  
  10.    // 先执行就是异步,后执行就是同步  
  11.    NSLog(@"come here");  

执行结果如下:

由此可见主队列中调度任务是异步执行的
再将执行队列改为全局队列和串行队列,得到的结果完全是一样的,由此可知该函数执行的是异步操作。

     GCD中有个函数能够保证某段代码在程序运行过程中只被执行1次!该函数如下:
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static dispatch_once_t onceToken;  
  2.     dispatch_once(&onceToken, ^{  
  3.          
  4.     })  

dispatch_once_t在头文件中得定义如下:
typedef long dispatch_once_t;
由此可知该类型是个long类型。当onceToken等于0时就会执行block代码。dispatch_once是线程安全的,只要涉及到线程安全就会涉及到锁,dispatch_once内部也有一把锁,性能比互斥锁高!
利用该函数我们可以来写一个单例模式
     单例模式可以保证在程序运行过程,一个类只有一个实例且该实例易于供外界访问,从而方便控制实例个数,并节约系统资源,当应用程序需要共享一份资源时就可以用单例模式来实现。单例模式分ARC与MRC两种情况,我们可以用宏判断是否为ARC环境

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #if __has_feature(objc_arc)  
  2. // ARC  
  3. #else  
  4. // MRC  
  5. #endif  

ARC环境下简单地单例模式:
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @implementation SoundTools  
  2. // 定义一个静态成员,保存唯一的实例  
  3. static id instance;  
  4.   
  5. // 保证对象只被分配一次内存空间,通过dispatch_once能够保证单例的分配和初始化是线程安全的  
  6. + (instancetype)allocWithZone:(struct _NSZone *)zone {  
  7.     static dispatch_once_t onceToken;  
  8.     dispatch_once(&onceToken, ^{  
  9.         instance = [super allocWithZone:zone];  
  10.     });  
  11.     return instance;  
  12. }  
  13.   
  14. // 保证对象只被初始化一次  
  15. + (instancetype)sharedSoundTools {  
  16.     static dispatch_once_t onceToken;  
  17.     dispatch_once(&onceToken, ^{  
  18.         instance = [[self alloc] init];  
  19.     });  
  20.     return instance;  
  21. }  
  22.   
  23. - (id)copyWithZone:(NSZone *)zone {  
  24.     return instance;  
  25. }  
  26. @end  
  27.   
  28. 测试代码如下:  
  29. - (void)viewDidLoad {  
  30.     [super viewDidLoad];  
  31.       
  32.     SoundTools *s1 = [SoundTools sharedSoundTools];  
  33.     NSLog(@"%p", s1);  
  34. }  
  35.   
  36. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  
  37.     SoundTools *s2 = [SoundTools sharedSoundTools];  
  38.       
  39.     NSLog(@"%p", s2);  
  40. }  


两个方法打印出来的地址完全一样!

在MRC环境下有如下代码:
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. // 定义一个静态成员,保存唯一的实例  
  2. static id instance;  
  3.   
  4. // 保证对象只被分配一次内存空间,通过dispatch_once能够保证单例的分配和初始化是线程安全的  
  5. + (instancetype)allocWithZone:(struct _NSZone *)zone {  
  6.     static dispatch_once_t onceToken;  
  7.     dispatch_once(&onceToken, ^{  
  8.         instance = [super allocWithZone:zone];  
  9.     });  
  10.     return instance;  
  11. }  
  12.   
  13. // 保证对象只被初始化一次  
  14. + (instancetype)sharedSoundTools {  
  15.     static dispatch_once_t onceToken;  
  16.     dispatch_once(&onceToken, ^{  
  17.         instance = [[self alloc] init];  
  18.     });  
  19.     return instance;  
  20. }  
  21.   
  22. - (id)copyWithZone:(NSZone *)zone {  
  23.     return instance;  
  24. }  
  25.   
  26. #pragma mark - MRC内存管理方法  
  27. /** 
  28.  因为单例的对象是保存在静态区的,因此需要重写 内存管理方法,取消默认的引用计数操作! 
  29.  */  
  30. // 默认会将引用计数-1  
  31. - (oneway void)release {  
  32.     // 什么也不做,跟highlight类似  
  33. }  
  34.   
  35. // 默认引用计数+1,同时返回一个对象  
  36. - (instancetype)retain {  
  37.     return instance;  
  38. }  
  39.   
  40. // 默认添加自动释放标记,延迟释放!  
  41. - (instancetype)autorelease {  
  42.     return instance;  
  43. }  
  44.   
  45. // 返回有多少个对象对当前对象引用的数值  
  46. - (NSUInteger)retainCount {  
  47.     // 出处:limits.h 会根据CPU的架构自行调整整数的长度  
  48.     return ULONG_MAX;  
  49. }  
0 0
原创粉丝点击