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() 方法

    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 對象,放到集合中,供下一次使用。

以上是個簡單的分析,下一章給點具體使用的代碼和心得。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章