Scheduler翻译成中文就是“调度”的意思,在RxJava里就是线程之间的调度,也就是线程之间的切换。
从图中可以简单看出,SingleScheduler、ComputationScheduler、IoScheduler、NewThreadScheduler的核心实现就是一个线程池,但该线程池里只会有一个线程,而newScheduledThreadPool是可以延迟、定时执行的,所以我们可以认为SingleScheduler、ComputationScheduler、IoScheduler、NewThreadScheduler的核心实现就是一个可定时、可延迟执行及轮询的特殊线程,下面简称线程。该线程是通过Observable的scheduleDirect方法来提交任务(基本上都是通过此方法来提交任务)。
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
final Worker w = createWorker();
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
DisposeTask task = new DisposeTask(decoratedRun, w);
w.schedule(task, delay, unit);
return task;
}
createWorker
是一个抽象的方法,在SingleScheduler、ComputationScheduler、IoScheduler、NewThreadScheduler中分别有不同的实现。
createWorker在SingleScheduler中的实现如下,在调用ScheduledWorker的schedule方法将任务交给线程执行。
public Worker createWorker() {
//传入一个有且只有一个线程的线程池,就是上面说的特殊线程
return new ScheduledWorker(executor.get());
}
public Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
...
tasks.add(sr);
try {
Future<?> f;
//将任务交给线程执行
if (delay <= 0L) {
f = executor.submit((Callable<Object>)sr);
} else {
f = executor.schedule((Callable<Object>)sr, delay, unit);
}
sr.setFuture(f);
} catch (RejectedExecutionException ex) {
...
}
SingleScheduler的原理比较简单,到此就完毕了。但线程是在那里创建的尼?其实在SingleScheduler的构造方法就已经创建了线程。由于SingleScheduler是单例实现,所有SingleScheduler中有且仅有一个线程。 那么当多任务且有耗时操作时,后面的任务就会等待。
public SingleScheduler(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
executor.lazySet(createExecutor(threadFactory));
}
//创建线程池
static ScheduledExecutorService createExecutor(ThreadFactory threadFactory) {
return SchedulerPoolFactory.create(threadFactory);
}
//是SchedulerPoolFactory中的create方法
public static ScheduledExecutorService create(ThreadFactory factory) {
//创建线程池
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, factory);
tryPutIntoPool(PURGE_ENABLED, exec);
return exec;
}
ComputationScheduler就比较麻烦一点了,图中可以看出ComputationScheduler里创建了一组线程。也是在构造方法中创建的,构造方法中调用start方法。
public ComputationScheduler(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
this.pool = new AtomicReference<FixedSchedulerPool>(NONE);
start();
}
public void start() {
//MAX_THREADS = cap(Runtime.getRuntime().availableProcessors(), Integer.getInteger(KEY_MAX_THREADS, 0));
FixedSchedulerPool update = new FixedSchedulerPool(MAX_THREADS, threadFactory);
//用update替代默认的NONE,NONE中没有任何线程创建
if (!pool.compareAndSet(NONE, update)) {
update.shutdown();
}
}
在start中创建了FixedSchedulerPool
对象,其中MAX_THREADS是根据Runtime.getRuntime().availableProcessors()
计算出来的。来看一下FixedSchedulerPool
对象的实现
static final class FixedSchedulerPool implements SchedulerMultiWorkerSupport {
final int cores;
final PoolWorker[] eventLoops;
long n;
FixedSchedulerPool(int maxThreads, ThreadFactory threadFactory) {
// initialize event loops
this.cores = maxThreads;
this.eventLoops = new PoolWorker[maxThreads];
//每个PoolWorker代表一个Executors.newScheduledThreadPool(1, factory)的实现
for (int i = 0; i < maxThreads; i++) {
this.eventLoops[i] = new PoolWorker(threadFactory);
}
}
//eventLoops中取出一个线程
public PoolWorker getEventLoop() {
int c = cores;
if (c == 0) {
return SHUTDOWN_WORKER;
}
// simple round robin, improvements to come
return eventLoops[(int)(n++ % c)];
}
...
@Override
public void createWorkers(int number, WorkerCallback callback) {
int c = cores;
if (c == 0) {
for (int i = 0; i < number; i++) {
callback.onWorker(i, SHUTDOWN_WORKER);
}
} else {
int index = (int)n % c;
for (int i = 0; i < number; i++) {
callback.onWorker(i, new EventLoopWorker(eventLoops[index]));
if (++index == c) {
index = 0;
}
}
n = index;
}
}
}
在FixedSchedulerPool
中创建了一组线程,当有任务时就取出其中一个线程来处理任务,如果任务超出线程数,那么其他任务就会等待。下面来看schedule方法
public Worker createWorker() {
//pool.get返回的就是一个FixedSchedulerPool对象
return new EventLoopWorker(pool.get().getEventLoop());
}
public Disposable schedule(@NonNull Runnable action) {
if (disposed) {
return EmptyDisposable.INSTANCE;
}
return poolWorker.scheduleActual(action, 0, TimeUnit.MILLISECONDS, serial);
}
由于poolWorker是NewThreadWorker的子类,所以就调用NewThreadWorker的scheduleActual
方法。
static final class PoolWorker extends NewThreadWorker {
PoolWorker(ThreadFactory threadFactory) {
super(threadFactory);
}
}
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);
if (parent != null) {
if (!parent.add(sr)) {
return sr;
}
}
Future<?> f;
try {
if (delayTime <= 0) {
f = executor.submit((Callable<Object>)sr);
} else {
f = executor.schedule((Callable<Object>)sr, delayTime, unit);
}
sr.setFuture(f);
} catch (RejectedExecutionException ex) {
if (parent != null) {
parent.remove(sr);
}
RxJavaPlugins.onError(ex);
}
return sr;
}
在scheduleActual
中也是将任务交给给线程执行,由于线程最多有MAX_THREADS个,所以当任务超过MAX_THREADS则会等待,直到其他任务执行完毕释放线程。
IoScheduler就有点意思,它有对Worker进行了缓存,实现了一个池CachedWorkerPool
,CachedWorkerPool
中有一个队列ConcurrentLinkedQueue
,它会存储每次使用的线程,同时也在CachedWorkerPool
中创建一个线程来不停的扫描(每隔60s扫描一次),判断是否有超时的线程,如果有就从ConcurrentLinkedQueue
中将线程移除掉。
static final class CachedWorkerPool implements Runnable {
//每个线程的存活时间
private final long keepAliveTime;
private final ConcurrentLinkedQueue<ThreadWorker> expiringWorkerQueue;
final CompositeDisposable allWorkers;
private final ScheduledExecutorService evictorService;
private final Future<?> evictorTask;
private final ThreadFactory threadFactory;
CachedWorkerPool(long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory) {
this.keepAliveTime = unit != null ? unit.toNanos(keepAliveTime) : 0L;
this.expiringWorkerQueue = new ConcurrentLinkedQueue<ThreadWorker>();
this.allWorkers = new CompositeDisposable();
this.threadFactory = threadFactory;
ScheduledExecutorService evictor = null;
Future<?> task = null;
if (unit != null) {
//创建一个新的线程,每keepAliveTime(默认是60s)执行一次,扫描是否有超时的线程
evictor = Executors.newScheduledThreadPool(1, EVICTOR_THREAD_FACTORY);
task = evictor.scheduleWithFixedDelay(this, this.keepAliveTime, this.keepAliveTime, TimeUnit.NANOSECONDS);
}
evictorService = evictor;
evictorTask = task;
}
@Override
public void run() {
//每次扫描执行的方法
evictExpiredWorkers();
}
ThreadWorker get() {
if (allWorkers.isDisposed()) {
return SHUTDOWN_THREAD_WORKER;
}
//判断队列是否为空,不为空则从队列中取出
while (!expiringWorkerQueue.isEmpty()) {
ThreadWorker threadWorker = expiringWorkerQueue.poll();
if (threadWorker != null) {
return threadWorker;
}
}
//如果没有缓存的线程,就重新创建
ThreadWorker w = new ThreadWorker(threadFactory);
allWorkers.add(w);
return w;
}
//当线程加入到队列中
void release(ThreadWorker threadWorker) {
// Refresh expire time before putting worker back in pool
//更新到期时间
threadWorker.setExpirationTime(now() + keepAliveTime);
expiringWorkerQueue.offer(threadWorker);
}
//如果线程超出存活时间就移除掉
void evictExpiredWorkers() {
if (!expiringWorkerQueue.isEmpty()) {
long currentTimestamp = now();
//遍历队列中的所有线程
for (ThreadWorker threadWorker : expiringWorkerQueue) {
if (threadWorker.getExpirationTime() <= currentTimestamp) {
if (expiringWorkerQueue.remove(threadWorker)) {
allWorkers.remove(threadWorker);
}
} else {
// Queue is ordered with the worker that will expire first in the beginning, so when we
// find a non-expired worker we can stop evicting.
break;
}
}
}
}
//当前时间
long now() {
return System.nanoTime();
}
//中断线程
void shutdown() {
allWorkers.dispose();
if (evictorTask != null) {
evictorTask.cancel(true);
}
if (evictorService != null) {
evictorService.shutdownNow();
}
}
}
了解CachedWorkerPool
后,IoScheduler基本上就没什么难点了,下面再来看createWorker
的实现,首先从CachedWorkerPool
中取出一个线程,然后在交给这个线程即可。
public Worker createWorker() {
return new EventLoopWorker(pool.get());
}
public Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull TimeUnit unit) {
if (tasks.isDisposed()) {
// don't schedule, we are unsubscribed
return EmptyDisposable.INSTANCE;
}
return threadWorker.scheduleActual(action, delayTime, unit, tasks);
}
}
//ThreadWorker继承与NewThreadWorker
static final class ThreadWorker extends NewThreadWorker {
//到期时间,到期后该线程就会被移除掉
private long expirationTime;
ThreadWorker(ThreadFactory threadFactory) {
super(threadFactory);
this.expirationTime = 0L;
}
//返回到期时间
public long getExpirationTime() {
return expirationTime;
}
//设置到期时间
public void setExpirationTime(long expirationTime) {
this.expirationTime = expirationTime;
}
}
从上面看出ThreadWorker
有一个到期时间,如果到期后就会被销毁,否则继续存在。
NewThreadScheduler
就比较简单,直接来一个任务就创建一个线程。
public Worker createWorker() {
return new NewThreadWorker(threadFactory);
}
这里直接返回NewThreadWorker
,这个类比较简单。
public class NewThreadWorker extends Scheduler.Worker implements Disposable {
private final ScheduledExecutorService executor;
volatile boolean disposed;
public NewThreadWorker(ThreadFactory threadFactory) {
//创建一个线程,前面已经介绍
executor = SchedulerPoolFactory.create(threadFactory);
}
@NonNull
@Override
public Disposable schedule(@NonNull final Runnable run) {
return schedule(run, 0, null);
}
@NonNull
@Override
public Disposable schedule(@NonNull final Runnable action, long delayTime, @NonNull TimeUnit unit) {
if (disposed) {
return EmptyDisposable.INSTANCE;
}
return scheduleActual(action, delayTime, unit, null);
}
//提交任务给线程池,也就是前面说的特殊线程
public Disposable scheduleDirect(final Runnable run, long delayTime, TimeUnit unit) {
ScheduledDirectTask task = new ScheduledDirectTask(RxJavaPlugins.onSchedule(run));
try {
Future<?> f;
if (delayTime <= 0L) {
f = executor.submit(task);
} else {
f = executor.schedule(task, delayTime, unit);
}
task.setFuture(f);
return task;
} catch (RejectedExecutionException ex) {
RxJavaPlugins.onError(ex);
return EmptyDisposable.INSTANCE;
}
}
//提交任务给线程池,也就是前面说的特殊线程
public Disposable schedulePeriodicallyDirect(Runnable run, long initialDelay, long period, TimeUnit unit) {
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
if (period <= 0L) {
InstantPeriodicTask periodicWrapper = new InstantPeriodicTask(decoratedRun, executor);
try {
Future<?> f;
if (initialDelay <= 0L) {
f = executor.submit(periodicWrapper);
} else {
f = executor.schedule(periodicWrapper, initialDelay, unit);
}
periodicWrapper.setFirst(f);
} catch (RejectedExecutionException ex) {
RxJavaPlugins.onError(ex);
return EmptyDisposable.INSTANCE;
}
return periodicWrapper;
}
ScheduledDirectPeriodicTask task = new ScheduledDirectPeriodicTask(decoratedRun);
try {
Future<?> f = executor.scheduleAtFixedRate(task, initialDelay, period, unit);
task.setFuture(f);
return task;
} catch (RejectedExecutionException ex) {
RxJavaPlugins.onError(ex);
return EmptyDisposable.INSTANCE;
}
}
//提交任务给线程池,也就是前面说的特殊线程
@NonNull
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);
if (parent != null) {
if (!parent.add(sr)) {
return sr;
}
}
Future<?> f;
try {
if (delayTime <= 0) {
f = executor.submit((Callable<Object>)sr);
} else {
f = executor.schedule((Callable<Object>)sr, delayTime, unit);
}
sr.setFuture(f);
} catch (RejectedExecutionException ex) {
if (parent != null) {
parent.remove(sr);
}
RxJavaPlugins.onError(ex);
}
return sr;
}
//取消线程执行
@Override
public void dispose() {
if (!disposed) {
disposed = true;
executor.shutdownNow();
}
}
//停止线程
public void shutdown() {
if (!disposed) {
disposed = true;
executor.shutdown();
}
}
//是否已经取消
@Override
public boolean isDisposed() {
return disposed;
}
}
TrampolineScheduler
跟线程没任何关系,默认在任务所在的线程,在Android中,TrampolineScheduler
无法做耗时操作,如果要做耗时操作的话则需要开启子线程,否则有可能会产生ANR。TrampolineScheduler
主要是实现了PriorityBlockingQueue
,它是一个优先级队列,所以TrampolineScheduler
仅仅是把任务添加到这个队列并执行。
public Worker createWorker() {
return new TrampolineWorker();
}
static final class TrampolineWorker extends Scheduler.Worker implements Disposable {
final PriorityBlockingQueue<TimedRunnable> queue = new PriorityBlockingQueue<TimedRunnable>();
private final AtomicInteger wip = new AtomicInteger();
final AtomicInteger counter = new AtomicInteger();
volatile boolean disposed;
//添加任务
@NonNull
@Override
public Disposable schedule(@NonNull Runnable action) {
return enqueue(action, now(TimeUnit.MILLISECONDS));
}
@NonNull
@Override
public Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull TimeUnit unit) {
long execTime = now(TimeUnit.MILLISECONDS) + unit.toMillis(delayTime);
//将任务添加到队列
return enqueue(new SleepingRunnable(action, this, execTime), execTime);
}
Disposable enqueue(Runnable action, long execTime) {
if (disposed) {
return EmptyDisposable.INSTANCE;
}
final TimedRunnable timedRunnable = new TimedRunnable(action, execTime, counter.incrementAndGet());
queue.add(timedRunnable);
//执行任务
if (wip.getAndIncrement() == 0) {
int missed = 1;
for (;;) {
for (;;) {
if (disposed) {
queue.clear();
return EmptyDisposable.INSTANCE;
}
final TimedRunnable polled = queue.poll();
if (polled == null) {
break;
}
if (!polled.disposed) {
polled.run.run();
}
}
missed = wip.addAndGet(-missed);
if (missed == 0) {
break;
}
}
return EmptyDisposable.INSTANCE;
} else {
// queue wasn't empty, a parent is already processing so we just add to the end of the queue
return Disposables.fromRunnable(new AppendToQueueTask(timedRunnable));
}
}
@Override
public void dispose() {
disposed = true;
}
@Override
public boolean isDisposed() {
return disposed;
}
final class AppendToQueueTask implements Runnable {
final TimedRunnable timedRunnable;
AppendToQueueTask(TimedRunnable timedRunnable) {
this.timedRunnable = timedRunnable;
}
@Override
public void run() {
timedRunnable.disposed = true;
queue.remove(timedRunnable);
}
}
}
HandlerScheduler
仅在android中有使用,主要是用于切换主线程,对于Android开发者来说就太熟悉了,就不多叙述。
public Worker createWorker() {
return new HandlerWorker(handler, async);
}
private static final class HandlerWorker extends Worker {
private final Handler handler;
private final boolean async;
private volatile boolean disposed;
HandlerWorker(Handler handler, boolean async) {
this.handler = handler;
this.async = async;
}
@Override
@SuppressLint("NewApi") // Async will only be true when the API is available to call.
public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
if (run == null) throw new NullPointerException("run == null");
if (unit == null) throw new NullPointerException("unit == null");
if (disposed) {
return Disposables.disposed();
}
run = RxJavaPlugins.onSchedule(run);
ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);
Message message = Message.obtain(handler, scheduled);
message.obj = this; // Used as token for batch disposal of this worker's runnables.
if (async) {
message.setAsynchronous(true);
}
handler.sendMessageDelayed(message, unit.toMillis(delay));
// Re-check disposed state for removing in case we were racing a call to dispose().
if (disposed) {
handler.removeCallbacks(scheduled);
return Disposables.disposed();
}
return scheduled;
}
@Override
public void dispose() {
disposed = true;
handler.removeCallbacksAndMessages(this /* token */);
}
@Override
public boolean isDisposed() {
return disposed;
}
}
关于RxJava中的Schedulers就分析完毕了,这里来总结一下: