RxJava 线程切换 ,源码分析(二)

RxJava 比较方便的一点在于线程间的切换,我们可以从上往下下,并且随时实现线程的切换,看个简单的代码
 

   private static void initRxJava1(){

        Observable
                .create(new Observable.OnSubscribe<String>() {
                    @Override
                    public void call(Subscriber<? super String> subscriber) {
                        System.out.println(" create    "  +  Thread.currentThread().getName() );
                        subscriber.onNext("hi");
                        subscriber.onCompleted();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        System.out.println(  "onCompleted  " );
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        System.out.println(s + "     "  +  Thread.currentThread().getName());
                    }
                });
    }

打印的结果为

 create    RxIoScheduler-3
hi     RxIoScheduler-2
onCompleted

如果我们把 observeOn(Schedulers.io()) 方法中的 Schedulers.io() 替换为 Schedulers.immediate(),再次打印,结果为

 create    RxIoScheduler-2
hi     RxIoScheduler-2
onCompleted

从上面的例子中,可以看出,io() 和 immediate() 的含义不一样:io() 是新开一个线程, immediate() 是使用当前线程,我们看看调用的源码


Schedulers:

    public static Scheduler io() {
        return RxJavaHooks.onIOScheduler(getInstance().ioScheduler);
    }

    private Schedulers() {
        ...
        Scheduler io = hook.getIOScheduler();
        if (io != null) {
            ioScheduler = io;
        } else {
            ioScheduler = RxJavaSchedulersHook.createIoScheduler();
        }
        ...
    }

RxJavaSchedulersHook:

    public static Scheduler createIoScheduler() {
        return createIoScheduler(new RxThreadFactory("RxIoScheduler-"));
    }

    public static Scheduler createIoScheduler(ThreadFactory threadFactory) {
        if (threadFactory == null) {
            throw new NullPointerException("threadFactory == null");
        }
        return new CachedThreadScheduler(threadFactory);
    }


到此,我们能找到 CachedThreadScheduler 类和 RxThreadFactory 类,先看看 RxThreadFactory,看名字就是个工厂的功能

public final class RxThreadFactory extends AtomicLong implements ThreadFactory {
    private static final long serialVersionUID = -8841098858898482335L;

    public static final ThreadFactory NONE = new ThreadFactory() {
        @Override public Thread newThread(Runnable r) {
            throw new AssertionError("No threads allowed.");
        }
    };

    final String prefix;

    public RxThreadFactory(String prefix) {
        this.prefix = prefix;
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, prefix + incrementAndGet());
        t.setDaemon(true);
        return t;
    }
}

这里面核心的方法就是 newThread(),创建线程用的,构造方法中传入 Runnable 和方法名,incrementAndGet() 是 ++ 的意思,原子级别的。再看看 subscribeOn() 方法的源码


Observable:
   

 public final Observable<T> subscribeOn(Scheduler scheduler) {
        if (this instanceof ScalarSynchronousObservable) {
            return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler);
        }
        return create(new OperatorSubscribeOn<T>(this, scheduler));
    }


此时的 this 是 Observable 类型,因此执行if外面的方法,看看 OperatorSubscribeOn 代码

public final class OperatorSubscribeOn<T> implements OnSubscribe<T> {

    final Scheduler scheduler;
    final Observable<T> source;

    public OperatorSubscribeOn(Observable<T> source, Scheduler scheduler) {
        this.scheduler = scheduler;
        this.source = source;
    }

    @Override
    public void call(final Subscriber<? super T> subscriber) {
        final Worker inner = scheduler.createWorker();
        subscriber.add(inner);
        inner.schedule(new Action0() {
            @Override
            public void call() {
                ...
            }
        });
    }
}

省略的部分是回调外面传进来的接口,可以忽略,重点看一下 scheduler.createWorker() 和 inner.schedule() 这两个部分,创建了 Worker 和执行了回调,这里的 scheduler 就是上面提到的 CachedThreadScheduler 类型的对象,看看 createWorker() 方法

扫描二维码关注公众号,回复: 9779645 查看本文章
    public Worker createWorker() {
        return new EventLoopWorker(pool.get());
    }

pool 是什么,看看代码,它是 AtomicReference<CachedWorkerPool> 类型的对象,在 CachedThreadScheduler 的构造方法中创建,在 start() 中赋值

    public CachedThreadScheduler(ThreadFactory threadFactory) {
        this.threadFactory = threadFactory;
        this.pool = new AtomicReference<CachedWorkerPool>(NONE);
        start();
    }
    
    @Override
    public void start() {
        CachedWorkerPool update =
            new CachedWorkerPool(threadFactory, KEEP_ALIVE_TIME, KEEP_ALIVE_UNIT);
        if (!pool.compareAndSet(NONE, update)) {
            update.shutdown();
        }
    }

也就是说,构造方法中创建了pool对象,并且创建了 CachedWorkerPool 对象,然后把 CachedWorkerPool 装到了pool对象中; pool.get() 对应的就是 CachedWorkerPool。看看 EventLoopWorker 中的 schedule() 方法

        @Override
        public Subscription schedule(Action0 action) {
            return schedule(action, 0, null);
        }

        @Override
        public Subscription schedule(final Action0 action, long delayTime, TimeUnit unit) {
            ...
            ScheduledAction s = threadWorker.scheduleActual(new Action0() {
                @Override
                public void call() {
                    if (isUnsubscribed()) {
                        return;
                    }
                    action.call();
                }
            }, delayTime, unit);
            innerSubscription.add(s);
            s.addParent(innerSubscription);
            return s;
        }

注意,这里面有个重点:threadWorker.scheduleActual() 方法。先看看 threadWorker 是什么,它是在 EventLoopWorker 的构造方法中,调用了 CachedWorkerPool 的 get() 方法获取的对象,

CachedWorkerPool:

        ThreadWorker get() {
            if (allWorkers.isUnsubscribed()) {
                return SHUTDOWN_THREADWORKER;
            }
            while (!expiringWorkerQueue.isEmpty()) {
                ThreadWorker threadWorker = expiringWorkerQueue.poll();
                if (threadWorker != null) {
                    return threadWorker;
                }
            }
            ThreadWorker w = new ThreadWorker(threadFactory);
            allWorkers.add(w);
            return w;
        }

从这段代码中可以看到,它有个集合复用的功能,如果集合中有,就使用;如果没有,就创建一个 ThreadWorker 对象,看看它的源码

    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 继承 NewThreadWorker,看看它的 scheduleActual() 方法

    public ScheduledAction scheduleActual(final Action0 action, long delayTime, TimeUnit unit) {
        Action0 decoratedAction = RxJavaHooks.onScheduledAction(action);
        ScheduledAction run = new ScheduledAction(decoratedAction);
        Future<?> f;
        if (delayTime <= 0) {
            f = executor.submit(run);
        } else {
            f = executor.schedule(run, delayTime, unit);
        }
        run.add(f);

        return run;
    }

第一行可以忽略,直接看第二行

public final class ScheduledAction extends AtomicReference<Thread> implements Runnable, Subscription {
    final Action0 action;

    public ScheduledAction(Action0 action) {
        this.action = action;
        this.cancel = new SubscriptionList();
    }

    @Override
    public void run() {
        try {
            lazySet(Thread.currentThread());
            action.call();
        } catch (OnErrorNotImplementedException e) {
            signalError(new IllegalStateException("Exception thrown on Scheduler.Worker thread. Add `onError` handling.", e));
        } catch (Throwable e) {
            signalError(new IllegalStateException("Fatal Exception thrown on Scheduler.Worker thread.", e));
        } finally {
            unsubscribe();
        }
    }
    ...
}

从代码上看,它实现了 Runnable 接口,run() 方法中执行的就是 action.call() 回调。重新回到 scheduleActual() 方法中,接下来就用 executor.submit(run) 或 executor.schedule(run, delayTime, unit) 方法。看看 NewThreadWorker 的构造方法

    public NewThreadWorker(ThreadFactory threadFactory) {
        ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, threadFactory);
        boolean cancelSupported = tryEnableCancelPolicy(exec);
        if (!cancelSupported && exec instanceof ScheduledThreadPoolExecutor) {
            registerExecutor((ScheduledThreadPoolExecutor)exec);
        }
        executor = exec;
    }

executor 是通过 Executors 的静态方法创建的对象,是 ScheduledThreadPoolExecutor 类型,是个线程池,因此 submit() 和 schedule() 都是开启线程执行 Runnable ,也就是说,子线程是在这里开启的。 ScheduledAction 中的 run() 方法结尾处,有个 unsubscribe() 方法,它是做一些回收的操作,schedule() 方法中调用了 ScheduledAction 的 addParent() 方法添加对象到 cancel 中,而 unsubscribe() 则释放。 

      void release(ThreadWorker threadWorker) {
            // Refresh expire time before putting worker back in pool
            threadWorker.setExpirationTime(now() + keepAliveTime);

            expiringWorkerQueue.offer(threadWorker);
        }


这一步是回收 ThreadWorker 对象,放到集合中,供下一次使用。

以上是个简单的分析,下一章给点具体使用的代码和心得。

发布了176 篇原创文章 · 获赞 11 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Deaht_Huimie/article/details/103130709