有的时候,在程序开发中,有些代码只想从程序启动就只执行一次,典型的应用场景就是“单例”

  1. // MARK: 一次性执行
  2. - (void)once {
  3. static dispatch_once_t onceToken;
  4. NSLog(@"%ld", onceToken);
  5. dispatch_once(&onceToken, ^{
  6. [NSThread sleepForTimeInterval:1.0];
  7. NSLog(@"一次性吗?");
  8. });
  9. NSLog(@"come here");
  10. }
  • dispatch 内部也有一把锁,是能够保证”线程安全”的!而且是苹果公司推荐使用的
  • 以下代码用于测试多线程的一次性执行
  1. - (void)demoOnce {
  2. for (int i = 0; i < 10; ++i) {
  3. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  4. [self once];
  5. });
  6. }
  7. }

单例测试

单例的特点

  1. 在内存中只有一个实例
  2. 提供一个全局的访问点

单例实现

  1. // 使用 dispatch_once 实现单例
  2. + (instancetype)sharedSingleton {
  3. static id instance;
  4. static dispatch_once_t onceToken;
  5. dispatch_once(&onceToken, ^{
  6. instance = [[self alloc] init];
  7. });
  8. return instance;
  9. }
  10. // 使用互斥锁实现单例
  11. + (instancetype)sharedSync {
  12. static id syncInstance;
  13. @synchronized(self) {
  14. if (syncInstance == nil) {
  15. syncInstance = [[self alloc] init];
  16. }
  17. }
  18. return syncInstance;
  19. }

面试时只要实现上面 sharedSingleton 方法即可

单例测试

  1. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  2. long largeNumber = 1000 * 1000;
  3. // 测试互斥锁
  4. CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
  5. for (long i = 0; i < largeNumber; ++i) {
  6. [Singleton sharedSync];
  7. }
  8. NSLog(@"互斥锁: %f", CFAbsoluteTimeGetCurrent() - start);
  9. // 测试 dispatch_once
  10. start = CFAbsoluteTimeGetCurrent();
  11. for (long i = 0; i < largeNumber; ++i) {
  12. [Singleton sharedSingleton];
  13. }
  14. NSLog(@"dispatch_once: %f", CFAbsoluteTimeGetCurrent() - start);
  15. }