首页 > 其他分享 >iOS开发基础112-GCD

iOS开发基础112-GCD

时间:2024-07-17 12:40:14浏览次数:14  
标签:group GCD self iOS dispatch queue 任务 112

Grand Central Dispatch(GCD)在iOS中的常见运用场景

GCD是Apple提供的多线程编程技术,旨在提供高效、轻量级的方式来执行并发任务。GCD使得管理线程变得简单且提高了应用程序的性能。以下是GCD在iOS中的一些常见运用场景,并详细介绍其底层原理。

1. 异步任务处理

场景:网络请求

使用GCD进行异步网络请求,使UI不被阻塞。

示例代码:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://example.com"]];
    dispatch_async(dispatch_get_main_queue(), ^{
        // 更新UI
        self.imageView.image = [UIImage imageWithData:data];
    });
});

原理解析:

  1. dispatch_async: 提交任务到一个队列,且不阻塞当前线程。
  2. dispatch_get_global_queue: 获取全局并发队列。
  3. dispatch_get_main_queue: 获取主队列,以在主线程上更新UI。

GCD的底层通过创建和管理轻量级的任务单元(blocks),并将这些任务提交到由系统管理的低层次队列(dispatch queues)。系统确保这些任务在适当的线程上执行,从而优化性能和资源使用。

2. 并发执行任务

场景:批量图片下载

示例代码:

dispatch_group_t group = dispatch_group_create();

for (NSString *urlString in urlArray) {
    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
        if (data) {
            UIImage *image = [UIImage imageWithData:data];
            // 处理图片
        }
        dispatch_group_leave(group);
    });
}

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // 所有任务完成后回到主线程
    [self updateUI];
});

原理解析:

  1. dispatch_group_create: 创建调度组。
  2. dispatch_group_enter: 进入调度组。
  3. dispatch_group_leave: 离开调度组。
  4. dispatch_group_notify: 所有调度组内任务完成后执行特定任务。

GCD的调度组允许将多个任务组合在一起,追踪这些任务的完成情况。当所有任务完成后,可以进行统一的后续操作。

3. 任务的延时执行

场景:避免频繁的UI更新(防抖)

示例代码:

dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC);
dispatch_after(delay, dispatch_get_main_queue(), ^{
    // 延时1秒执行的任务
    [self performUIUpdate];
});

原理解析:

  1. dispatch_time: 计算未来的时间点。
  2. dispatch_after: 在指定延迟后执行任务。

GCD处理定时任务时,底层会创建一个计时器,并在计时结束后将任务提交到相应的队列中执行。

4. 一次性执行

场景:单例模式

示例代码:

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    static MyClass *instance = nil;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

原理解析:

  1. dispatch_once: 确保代码块只执行一次。

dispatch_once使用底层的 atomic operations 确保线程安全,即使在并发访问的情况下也能保证代码块只被执行一次。

5. 线程同步

场景:访问共享资源

示例代码:

@property (nonatomic, strong) dispatch_queue_t syncQueue;

- (instancetype)init {
    self = [super init];
    if (self) {
        _syncQueue = dispatch_queue_create("com.example.syncQueue", DISPATCH_QUEUE_SERIAL);
    }
    return self;
}

- (void)updateSharedResource {
    dispatch_sync(self.syncQueue, ^{
        // 访问和修改共享资源
    });
}

原理解析:

  1. dispatch_queue_create: 创建一个串行队列。
  2. dispatch_sync: 同步执行任务。

使用同步队列确保对共享资源的访问和修改是线程安全的。GCD通过串行化执行保证数据库访问、文件读写等不发生竞争情况。

6. 定期任务

场景:游戏中的刷新逻辑或实时更新

示例代码:

@property (nonatomic, strong) dispatch_source_t timer;

- (void)startTimer {
    dispatch_queue_t queue = dispatch_get_main_queue();
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), 1.0 * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(self.timer, ^{
        // 定期运行的任务
        [self updateGameState];
    });
    dispatch_resume(self.timer);
}

- (void)stopTimer {
    dispatch_source_cancel(self.timer);
    self.timer = NULL;
}

原理解析:

  1. dispatch_source_create: 创建调度源,常用于计时器、文件描述符、信号等。
  2. dispatch_source_set_timer: 设置计时器的开始时间和重复间隔。
  3. dispatch_source_set_event_handler: 设置事件处理程序。

GCD的调度源基于"run loop"机制,可以高效地处理定期任务,同时通过驻留的内核对象来管理计时器等资源。

7. 信号量控制

场景:控制并发数量

示例代码:

dispatch_semaphore_t semaphore = dispatch_semaphore_create(3); // 最大并发数为3

for (NSString *urlString in urlArray) {
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
        if (data) {
            UIImage *image = [UIImage imageWithData:data];
            // 处理图片
        }
        dispatch_semaphore_signal(semaphore);
    });
}

原理解析:

  1. dispatch_semaphore_create: 创建信号量。
  2. dispatch_semaphore_wait: 等待信号。
  3. dispatch_semaphore_signal: 发送信号。

信号量通过计数机制控制并发线程的数量,GCD底层使用信号量的原子操作确保线程安全。

8. Barrier Block

场景:多读单写

示例代码:

dispatch_queue_t queue = dispatch_queue_create("com.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, ^{
    // 读操作
    [self readData];
});

dispatch_async(queue, ^{
    // 读操作
    [self readData];
});

dispatch_barrier_async(queue, ^{
    // 写操作
    [self writeData];
});

dispatch_async(queue, ^{
    // 读操作
    [self readData];
});

原理解析:

  1. DISPATCH_QUEUE_CONCURRENT: 创建并发队列。
  2. dispatch_barrier_async: 提交栅栏任务,确保它之前和之后的并发任务都完成,将其与其他任务隔离开来。

Barrier Block允许在并发队列中实现类似于数据库的多读单写机制,从而确保资源的一致性。

9. 主队列死锁问题

场景:防止死锁

示例代码:

// 在主队列上同步提交任务会导致死锁
dispatch_sync(dispatch_get_main_queue(), ^{
    NSLog(@"This will never be printed");
});

原理解析:

  1. 主队列是串行队列,如果在主线程上同步提交任务,会导致死锁,因为主线程自身正在等待提交的任务完成。

避免在主线程上同步提交任务,否则会导致严重的阻塞问题。GCD的底层实现通过检查pthread_main_np来判定当前是否在主线程上进行阻塞操作,如是则抛出异常或警告。

总结

GCD通过诸如dispatch queues、dispatch groups、dispatch sources和semaphores等基础设施,提供了一种高效、优雅的并发编程方式。其底层主要基于任务调度器、线程池和内核对象(如计时器、信号量)等组成。通过合理使用这些组件,开发者可以显著提高应用程序的响应速度和资源利用率。

标签:group,GCD,self,iOS,dispatch,queue,任务,112
From: https://www.cnblogs.com/chglog/p/18307064

相关文章

  • iOS开发基础110-Core Graphics应用场景
    CoreGraphics是一种强大的二维图形绘制框架,广泛应用于iOS开发中。以下是几个常见的运用场景以及对应的代码示例:1.自定义视图绘制通过覆盖UIView的drawRect:方法,可以自定义视图的外观。示例代码:#import<UIKit/UIKit.h>@interfaceCustomView:UIView@end@implementat......
  • iOS开发基础109-网络安全
    在iOS开发中,保障应用的网络安全是一个非常重要的环节。以下是一些常见的网络安全措施及对应的示例代码:Swift版1.使用HTTPS确保所有的网络请求使用HTTPS协议,以加密数据传输,防止中间人攻击。示例代码:在Info.plist中配置AppTransportSecurity(ATS):<key>NSAppTransportSecur......
  • iOS开发基础108-常见的编程范式
    1.面向过程编程(Process-OrientedProgramming,POP)代码示例(Swift)importUIKitclassViewController:UIViewController{overridefuncviewDidLoad(){super.viewDidLoad()printGreeting()printNumber(num:42)}/......
  • iOS开发基础107-直播
    在iOS平台上,直播技术已经很成熟,有许多强大的第三方框架可以帮助开发者轻松实现直播功能。当前主流的直播第三方框架包括但不限于:LFLiveKit:一款开源的直播推流SDK。PLMediaStreamingKit:由云天存提供的一站式音视频解决方案。AliyunPlayer:阿里云提供的音视频播放解决方案。A......
  • iOS开发基础105-Xcode收集Crashs的各种方法
    Xcode提供了一整套工具和功能来帮助开发者收集、分析和处理应用崩溃报告。通过这些工具,开发者可以追踪和解析崩溃日志,以更加准确和及时地修复问题。以下是详细介绍Xcode工具收集崩溃报告的各种方法。一、通过设备获取崩溃报告1.连接设备将iOS设备通过USB连接到您的Mac......
  • iOS开发基础106-Instruments
    Instruments是苹果公司提供的一款强大的分析和性能调试工具,集成在Xcode开发环境中。Instruments可帮助开发者分析和优化iOS、macOS应用,检测性能瓶颈、内存泄漏、CPU使用率、磁盘I/O等问题,从而提升应用的效率和用户体验。以下详细介绍Instruments的主要功能和使用方法......
  • iOS开发基础104-正向代理和反向代理
    正向代理和反向代理是计算机网络中两种重要的技术,它们在网络请求的传递和管理上扮演着不同的角色。下面将详细介绍这两者的概念、优缺点,并探讨它们在iOS开发中的应用。一、正向代理1.概念正向代理是一种代理服务器,客户端向代理服务器发送请求,由代理服务器转发请求到目标服务器......
  • iOS开发基础103-APP之间跳转
    iOS提供了多种方式来实现应用之间的相互跳转。其中,URLSchemes和UniversalLinks是两种主要的方法。下面详细介绍这两种方法,并提供相应的示例代码,同时对它们的优缺点进行分析。一、URLSchemes1.什么是URLSchemesURLSchemes是一种基于URL的通讯方式,允许一个应用通过指定的UR......
  • iOS开发基础102-后台保活方案
    iOS系统在后台执行程序时,有严格的限制,为了更好地管理资源和电池寿命,iOS会限制应用程序在后台的运行时间。然而,iOS提供了一些特定的策略和技术,使得应用程序可以在特定场景下保持后台运行(即“后台保活”)。以下是iOS中几种常见的后台保活方案,并附上示例代码:一、后台任务利用beginBa......
  • iOS开发基础101-指纹和面部识别
    在iOS开发中,使用FaceID和TouchID可以为用户提供安全的生物识别认证,而手势识别(GestureRecognition)可以增加用户交互的便利性和灵活性。下面将详细介绍这三种技术,并给出如何封装一个统一的工具类来供外部使用。一、FaceID与TouchID1.设置与配置在使用FaceID和TouchID之前,需要在......