[TOC]
代码居多,没有过的分析,主要是缕缕线索
RxSwift之调度器
Scheduler作为RxSwift中的核心之一的调度者,主要是切换任务在线程或者队列的工作机制
####调度器的种类
CurrentThreadScheduler:获取当前调度MainScheduler:主调度,主要是切换到主线程的SerialDispatchQueueScheduler:串行调度,使用这个调度运行串行任务,基于GCD的串行队列封装ConcurrentDispatchQueueScheduler:并行调度,使用这个调度器运行并行任务,基于GCD的并行队列封装OperationQueueScheduler: 操作队列调度,基于NSOperationQueue封装
调度器的继承结构

各调度器的实现
MainSheduler调度器
public final class MainScheduler : SerialDispatchQueueScheduler {
private let _mainQueue: DispatchQueue
var numberEnqueued = AtomicInt(0)
/// Initializes new instance of `MainScheduler`.
public init() {
self._mainQueue = DispatchQueue.main
super.init(serialQueue: self._mainQueue)
}
}
代码分析
MainScheduler继承自SerialDispatchQueueScheduler串行调度器,在构造函数中主队列的确定根据是self._mainQueue = DispatchQueue.main,和调用父类的构造方法,传入队列类型
2.SerialDispatchQueueScheduler调度器
public class SerialDispatchQueueScheduler : SchedulerType {
public typealias TimeInterval = Foundation.TimeInterval
public typealias Time = Date
/// - returns: Current time.
public var now : Date {
return Date()
}
let configuration: DispatchQueueConfiguration
/**
Constructs new `SerialDispatchQueueScheduler` that wraps `serialQueue`.
- parameter serialQueue: Target dispatch queue.
- parameter leeway: The amount of time, in nanoseconds, that the system will defer the timer.
*/
init(serialQueue: DispatchQueue, leeway: DispatchTimeInterval = DispatchTimeInterval.nanoseconds(0)) {
self.configuration = DispatchQueueConfiguration(queue: serialQueue, leeway: leeway)
}
public convenience init(internalSerialQueueName: String, serialQueueConfiguration: ((DispatchQueue) -> Void)? = nil, leeway: DispatchTimeInterval = DispatchTimeInterval.nanoseconds(0)) {
let queue = DispatchQueue(label: internalSerialQueueName, attributes: [])
serialQueueConfiguration?(queue)
self.init(serialQueue: queue, leeway: leeway)
}
}
代码分析
这段代码说实话啥也没看出来,只是把传进来的queue和leeway存起来,这里应该的具体使用在父类中有具体实现或者对应的扩展中
3.ConcurrentDispatchQueueScheduler调度器
public class ConcurrentDispatchQueueScheduler: SchedulerType {
public typealias TimeInterval = Foundation.TimeInterval
public typealias Time = Date
public var now : Date {
return Date()
}
let configuration: DispatchQueueConfiguration
public init(queue: DispatchQueue, leeway: DispatchTimeInterval = DispatchTimeInterval.nanoseconds(0)) {
self.configuration = DispatchQueueConfiguration(queue: queue, leeway: leeway)
}
@available(iOS 8, OSX 10.10, *)
public convenience init(qos: DispatchQoS, leeway: DispatchTimeInterval = DispatchTimeInterval.nanoseconds(0)) {
self.init(queue: DispatchQueue(
label: "rxswift.queue.\(qos)",
qos: qos,
attributes: [DispatchQueue.Attributes.concurrent],
target: nil),
leeway: leeway
)
}
}
代码分析
设置了队列类型attributes的设置,concurrent为并行
4.OperationQueueScheduler调度器
public class OperationQueueScheduler: ImmediateSchedulerType {
public let operationQueue: OperationQueue
public let queuePriority: Operation.QueuePriority
public init(operationQueue: OperationQueue, queuePriority: Operation.QueuePriority = .normal) {
self.operationQueue = operationQueue
self.queuePriority = queuePriority
}
}
5.CurrentThreadScheduler调度器
public class CurrentThreadScheduler : ImmediateSchedulerType {
typealias ScheduleQueue = RxMutableBox<Queue<ScheduledItemType>>
/// The singleton instance of the current thread scheduler.
public static let instance = CurrentThreadScheduler()
private static var isScheduleRequiredKey: pthread_key_t = { () -> pthread_key_t in
let key = UnsafeMutablePointer<pthread_key_t>.allocate(capacity: 1)
defer {
#if swift(>=4.1)
key.deallocate()
#else
key.deallocate(capacity: 1)
#endif
}
static var queue : ScheduleQueue? {
get {
return Thread.getThreadLocalStorageValueForKey(CurrentThreadSchedulerQueueKey.instance)
}
set {
Thread.setThreadLocalStorageValue(newValue, forKey: CurrentThreadSchedulerQueueKey.instance)
}
}
/// Gets a value that indicates whether the caller must call a `schedule` method.
public static fileprivate(set) var isScheduleRequired: Bool {
get {
return pthread_getspecific(CurrentThreadScheduler.isScheduleRequiredKey) == nil
}
set(isScheduleRequired) {
if pthread_setspecific(CurrentThreadScheduler.isScheduleRequiredKey, isScheduleRequired ? nil : scheduleInProgressSentinel) != 0 {
rxFatalError("pthread_setspecific failed")
}
}
}
/**
Schedules an action to be executed as soon as possible on current thread.
If this method is called on some thread that doesn't have `CurrentThreadScheduler` installed, scheduler will be
automatically installed and uninstalled after all work is performed.
- parameter state: State passed to the action to be executed.
- parameter action: Action to be executed.
- returns: The disposable object used to cancel the scheduled action (best effort).
*/
public func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
if CurrentThreadScheduler.isScheduleRequired {
CurrentThreadScheduler.isScheduleRequired = false
let disposable = action(state)
defer {
CurrentThreadScheduler.isScheduleRequired = true
CurrentThreadScheduler.queue = nil
}
guard let queue = CurrentThreadScheduler.queue else {
return disposable
}
while let latest = queue.value.dequeue() {
if latest.isDisposed {
continue
}
latest.invoke()
}
return disposable
}
let existingQueue = CurrentThreadScheduler.queue
let queue: RxMutableBox<Queue<ScheduledItemType>>
if let existingQueue = existingQueue {
queue = existingQueue
}
else {
queue = RxMutableBox(Queue<ScheduledItemType>(capacity: 1))
CurrentThreadScheduler.queue = queue
}
let scheduledItem = ScheduledItem(action: action, state: state)
queue.value.enqueue(scheduledItem)
return scheduledItem
}
}
代码分许
当前调度,默认就是在当前线程调度执行,内部有绑定queue的机制以及存储和判断要不要调用schedule
6.SchedulerType协议及扩展实现
public protocol SchedulerType: ImmediateSchedulerType {
/// - returns: Current time.
var now : RxTime {
get
}
/**
Schedules an action to be executed.
- parameter state: State passed to the action to be executed.
- parameter dueTime: Relative time after which to execute the action.
- parameter action: Action to be executed.
- returns: The disposable object used to cancel the scheduled action (best effort).
*/
func scheduleRelative<StateType>(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable
/**
Schedules a periodic piece of work.
- parameter state: State passed to the action to be executed.
- parameter startAfter: Period after which initial work should be run.
- parameter period: Period for running the work periodically.
- parameter action: Action to be executed.
- returns: The disposable object used to cancel the scheduled action (best effort).
*/
func schedulePeriodic<StateType>(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable
}
extension SchedulerType {
/**
Periodic task will be emulated using recursive scheduling.
- parameter state: Initial state passed to the action upon the first iteration.
- parameter startAfter: Period after which initial work should be run.
- parameter period: Period for running the work periodically.
- returns: The disposable object used to cancel the scheduled recurring action (best effort).
*/
public func schedulePeriodic<StateType>(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable {
let schedule = SchedulePeriodicRecursive(scheduler: self, startAfter: startAfter, period: period, action: action, state: state)
return schedule.start()
}
func scheduleRecursive<State>(_ state: State, dueTime: RxTimeInterval, action: @escaping (State, AnyRecursiveScheduler<State>) -> Void) -> Disposable {
let scheduler = AnyRecursiveScheduler(scheduler: self, action: action)
scheduler.schedule(state, dueTime: dueTime)
return Disposables.create(with: scheduler.dispose)
}
}
7.ImmediateSchedulerType调度协议实现
extension ImmediateSchedulerType {
/**
Schedules an action to be executed recursively.
- parameter state: State passed to the action to be executed.
- parameter action: Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in recursive invocation state.
- returns: The disposable object used to cancel the scheduled action (best effort).
*/
public func scheduleRecursive<State>(_ state: State, action: @escaping (_ state: State, _ recurse: (State) -> Void) -> Void) -> Disposable {
let recursiveScheduler = RecursiveImmediateScheduler(action: action, scheduler: self)
recursiveScheduler.schedule(state)
return Disposables.create(with: recursiveScheduler.dispose)
}
}
代码分析
在6是通过构造了一个SchedulePeriodicRecursive或者AnyRecursiveScheduler;在7中RecursiveImmediateScheduler
SchedulePeriodicRecursive和RecursiveImmediateScheduler是在一个swift文件中,内部主要的实现使用过实现了一个schedule方法,具体这里就不赘述了,也没特别仔细看,AnyRecursiveScheduler也是类似的
GCD实现一个异步处理后回到主线程
DispatchQueue.init(label: "com.baozi.testGCD",qos: .default,attributes:.concurrent).async {
var num = 0
for i in 0...250{
num += I
}
DispatchQueue.main.sync {
print("total Baozi count :\(num) \(Thread.current)")
}
}
RxSwift实现异步回到主线程🌰
Observable<Any>.create { (observer) -> Disposable in
var num = 0
for i in 0...250{
num += I
}
observer.onNext(num)
return Disposables.create()
}
.subscribeOn(SerialDispatchQueueScheduler.init(internalSerialQueueName: "com.baozi.rxswift"))
.observeOn(MainScheduler.instance)
.subscribe(onNext: { (val) in
print(val)
}).disposed(by: disposeBag)
调度器的原理逻辑
写个小🌰,开始探究一番吧
let _ = Observable.of(1,2,3,4,5).subscribeOn(SerialDispatchQueueScheduler.init(internalSerialQueueName: "com.baozi.rxswift"))
.subscribe(onNext: { (val) in
print(val)
}).disposed(by: disposeBag)
let _ = Observable.of(1,2,3,4,5)
.observeOn(MainScheduler.instance)
.subscribe(onNext: { (val) in
print(val)
}).disposed(by: disposeBag)
怎么实现的多线程的调度,可以清楚地看到主要是依靠subscribeOn和observeOn指定相关的调度,实际就是制定了相关的线程
Now,两者差不多感觉,看看subscribeOn吧
public func subscribeOn(_ scheduler: ImmediateSchedulerType)
-> Observable<Element> {
return SubscribeOn(source: self, scheduler: scheduler)
}
SubscribeOn的实现如下
final private class SubscribeOn<Ob: ObservableType>: Producer<Ob.Element> {
let source: Ob
let scheduler: ImmediateSchedulerType
init(source: Ob, scheduler: ImmediateSchedulerType) {
self.source = source
self.scheduler = scheduler
}
override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Ob.Element {
let sink = SubscribeOnSink(parent: self, observer: observer, cancel: cancel)
let subscription = sink.run()
return (sink: sink, subscription: subscription)
}
}
看起来和核心的逻辑很像,还有对应的Sink,源码上边确实有对应的Sink的实现,应该是同理的逻辑,这块应该还是核心逻辑的基础,还是要扎实下基础的