IOS GCD 使用(三)单例模式
一  Dispatch_once函数简介
 
        使用dispatch_once提价的代码块,即便你提交多次,只能执行一次。
  
 
      void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
     
 
    
     
 
    
     
 
    
 
    - (void)viewDidLoad
   
 
   {
 
       
   
    
 
   
 
       dispatch_once(&onceToken, ^(void)
{
dispatch_async(concurrentQueue,executedOnlyOnce);
});
dispatch_once(&onceToken, ^(void)
{
dispatch_async(concurrentQueue,executedOnlyOnce);
});
        
   
        
static dispatch_once_t testToken;
dispatch_once(&testToken, ^(void)
{
NSLog(@"####:Current thread = %@", [NSThread currentThread]);
});
 
         
}
  
    
 
  
        第一个参数是一个传出参数用来保存代码块在队列运行时被赋的值,如果你想让自己的代码只执行一次的话,你必须指定一个同样的标识符,其实它是long类型的长整数,即typedef long dispatch_once_t。
    
         第二个参数是一个代码块,这个代码块没有参数和返回值。
    
         dispatch_once 中的代码块默认的情况下在当前的线程内中执行(也就是被调用函数所在的线程)
    
     二 使用
    
       [super viewDidLoad]; 
   
        static dispatch_once_t onceToken;
void (^executedOnlyOnce)(void) = ^(void)
{
static NSUInteger numberOfEntries = 0;
numberOfEntries++;
NSLog(@"Executed %lu time(s) %@", (unsigned long)numberOfEntries,[NSThread currentThread]);
};
void (^executedOnlyOnce)(void) = ^(void)
{
static NSUInteger numberOfEntries = 0;
numberOfEntries++;
NSLog(@"Executed %lu time(s) %@", (unsigned long)numberOfEntries,[NSThread currentThread]);
};
{
dispatch_async(concurrentQueue,executedOnlyOnce);
});
dispatch_once(&onceToken, ^(void)
{
dispatch_async(concurrentQueue,executedOnlyOnce);
});
static dispatch_once_t testToken;
dispatch_once(&testToken, ^(void)
{
NSLog(@"####:Current thread = %@", [NSThread currentThread]);
});
}
     输出结果:
       
 
      
       
 
      
       
 
      
       
 
      
       
 
      
       
 
      
       
 
      
       
 
      
 
     
 
    
 
   
       2013-11-11 17:21:21.076 GCDDemo[1410:70b] ####:Current thread = <NSThread: 0x8a1e7c0>{name = (null), num = 1}
2013-11-11 17:21:21.076 GCDDemo[1410:2a03] Executed 1 time(s) <NSThread: 0x8a794c0>{name = (null), num = 2}
 
      
2013-11-11 17:21:21.076 GCDDemo[1410:2a03] Executed 1 time(s) <NSThread: 0x8a794c0>{name = (null), num = 2}
       观察发现:
      
       1.使用了同一个dispatch_once_t标识提价的代码块只运行了一次。
      
       2.使用dispatch_once提交的代码块默认情况下在当前线程内中执行(也就是被调用函数所在的线程),上面例子在主线程中提交的,所以打印的线程号为1.
      
       3.为了在其他线程中运行dipsatch_once提交的代码块,可以将代码块的任务提交到GCD队列中。
      
       三 单例模式
      
              可以利用dispatch_once的性质来实现单例模式,将我们自定义类的对象创建过程封装到一个代码块中,然后以dispath_once的方式来提交。
      
       看代码:
      
           +(MyClass*)  sharedInstance
{
static MyClass *_sharedMyClass;
static dispatch_once_t token;
        
dispatch_once(&token,^{ _sharedMyClass = [[MyClass alloc] initWith:something];} );
        
return _sharedMyClass;
}
 
      
{
static MyClass *_sharedMyClass;
static dispatch_once_t token;
dispatch_once(&token,^{ _sharedMyClass = [[MyClass alloc] initWith:something];} );
return _sharedMyClass;
}
 
   注意:  1.使用dispatch_once是线程安全的。
  
 
                2.使用上面例子来实现的单例是“伪单例”,也就是说只有当使用者用MyClass *obj = [MyClass shardInstance];方式来取得对象时候才算是单例,但是我们无法阻止其直接只用alloc来创建自己的对象。
  
                    
                
                
            
        
浙公网安备 33010602011771号