ReactiveCocoa 中 RACScheduler 是如何封装GCD的
原文地址:http://www.jianshu.com/p/980ffdf3ed8c
前言在使用ReactiveCocoa 过程中,Josh Abernathy和Justin Spahr-Summers两位大神为了能让RAC的使用者更畅快的在沉浸在FRP的世界里,更好的进行并发编程,于是就对GCD进行了一次封装,并与RAC的各大组件进行了完美的整合。 自从有了RACScheduler以后,使整个RAC并发编程的代码里面更加和谐统一,更加顺手,更加“ReactiveCocoa”。 目录
一. RACScheduler是如何封装GCD的RACScheduler在ReactiveCocoa中到底是干嘛的呢?处于什么地位呢?官方给出的定义如下: Schedulers are used to control when and where work is performed
RACScheduler在ReactiveCocoa中是用来控制一个任务,何时何地被执行。它主要是用来解决ReactiveCocoa中并发编程的问题的。 RACScheduler的实质是对GCD的封装,底层就是GCD实现的。 要分析RACScheduler,先来回顾一下GCD。 众所周知,在GCD中,Dispatch Queue主要分为2类,Serial Dispatch Queue 和 Concurrent Dispatch Queue 。其中Serial Dispatch Queue是等待现在执行中处理结束的队列,Concurrent Dispatch Queue是不等待现在执行中处理结束的队列。 生成Dispatch Queue的方法也有2种,第一种方式是通过GCD的API生成Dispatch Queue。 生成Serial Dispatch Queue dispatch_queue_t serialDispatchQueue = dispatch_queue_create("com.gcd.SerialDispatchQueue",DISPATCH_QUEUE_SERIAL);
生成Concurrent Dispatch Queue dispatch_queue_t concurrentDispatchQueue = dispatch_queue_create("com.gcd.ConcurrentDispatchQueue",DISPATCH_QUEUE_CONCURRENT);
第二种方法是直接获取系统提供的Dispatch Queue。系统提供的也分为2类,Main Dispatch Queue 和 Global Dispatch Queue。Main Dispatch Queue 对应着是Serial Dispatch Queue,Global Dispatch Queue 对应着是Concurrent Dispatch Queue。 Global Dispatch Queue主要分为8种。 首先是以下4种,分别是优先级对应Qos的情况。
- DISPATCH_QUEUE_PRIORITY_HIGH: QOS_CLASS_USER_INITIATED - DISPATCH_QUEUE_PRIORITY_DEFAULT: QOS_CLASS_DEFAULT - DISPATCH_QUEUE_PRIORITY_LOW: QOS_CLASS_UTILITY - DISPATCH_QUEUE_PRIORITY_BACKGROUND: QOS_CLASS_BACKGROUND 其次是,是否支持 overcommit。加上上面4个优先级,所以一共8种Global Dispatch Queue。带有 overcommit 的队列表示每当有任务提交时,系统都会新开一个线程处理,这样就不会造成某个线程过载(overcommit)。 回到RACScheduler中来,RACScheduler既然是对GCD的封装,那么上述说的这些类型也都有其一一对应的封装。
typedef enum : long {
RACSchedulerPriorityHigh = DISPATCH_QUEUE_PRIORITY_HIGH,RACSchedulerPriorityDefault = DISPATCH_QUEUE_PRIORITY_DEFAULT,RACSchedulerPriorityLow = DISPATCH_QUEUE_PRIORITY_LOW,RACSchedulerPriorityBackground = DISPATCH_QUEUE_PRIORITY_BACKGROUND,} RACSchedulerPriority;
首先是RACScheduler中的优先级,这里只封装了4种,也是分别对应GCD中的DISPATCH_QUEUE_PRIORITY_HIGH,DISPATCH_QUEUE_PRIORITY_DEFAULT,DISPATCH_QUEUE_PRIORITY_LOW,DISPATCH_QUEUE_PRIORITY_BACKGROUND。 RACScheduler有6个类方法,都是用来生成一个queue的。 + (RACScheduler *)immediateScheduler;
+ (RACScheduler *)mainThreadScheduler;
+ (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority name:(NSString *)name;
+ (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority;
+ (RACScheduler *)scheduler;
+ (RACScheduler *)currentScheduler;
接下来依次分析一下它们的底层实现。 1. immediateScheduler+ (instancetype)immediateScheduler {
static dispatch_once_t onceToken;
static RACScheduler *immediateScheduler;
dispatch_once(&onceToken,^{
immediateScheduler = [[RACImmediateScheduler alloc] init];
});
return immediateScheduler;
}
immediateScheduler底层实现就是生成了一个RACImmediateScheduler的单例。 RACImmediateScheduler 是继承自RACScheduler。 @interface RACImmediateScheduler : RACScheduler
@end
在RACScheduler中,每个种类的RACScheduler都会有一个name属性,名字也算是他们的标示。RACImmediateScheduler的name是@"com.ReactiveCocoa.RACScheduler.immediateScheduler" RACImmediateScheduler的作用和它的名字一样,是立即执行闭包里面的任务。 - (RACDisposable *)schedule:(void (^)(void))block {
NSCParameterAssert(block != NULL);
block();
return nil;
}
- (RACDisposable *)after:(NSDate *)date schedule:(NSCParameterAssert(date != nil);
NSCParameterAssert(block != NULL);
[NSThread sleepUntilDate:date];
block();
return nil;
}
在schedule:方法中,直接调用执行入参block( )闭包。在after: schedule:方法中,线程先睡眠,直到date的时刻,再醒过来执行入参block( )闭包。 - (RACDisposable *)after:(NSDate *)date repeatingEvery:(NSTimeInterval)interval withLeeway:(NSTimeInterval)leeway schedule:(NSCAssert(NO,@"+[RACScheduler immediateScheduler] does not support %@.",NSStringFromSelector(_cmd));
当然RACImmediateScheduler是不可能支持after: repeatingEvery: withLeeway: schedule:方法的。因为它的定义就是立即执行的,不应该repeat。
|
- c# – 将DateTime更改为午夜
- Flex操作Json数据示例 .
- 比较令人惊叹的FastDB和SQLite的RAMDISK内的性能对比
- c – 如何确定字符串是否包含在std :: vector的任何字符串中
- C++ 读文件 将文件内容读入到字符串string中的方法
- 有没有办法在Entity Framework PostgreSql中使用ARRAY
- c# – 哪些图形框架为Windows 8? MonoGame? OpenGL和Xaml
- ajax – 是否可以通过使用CNAME记录来允许跨域请求?
- 求教ORACLE中sysdate和current_timestamp的区别?
- “ORA-12541:TNS:无监听程序”错误 - listener.log日志达到