RxJava2 amb运算符抛出java.lang.InterruptedException

时间:2018-03-17 16:19:38

标签: android rx-java rx-java2

我正在使用Rxjava2 ambArray运算符。我创建了2个可观察的实验。

可观察1:

Observable<String> observable1 =
Observable.defer(new Callable<ObservableSource<? extends String>>() {
    @Override
    public ObservableSource<? extends String> call() throws Exception {
        return  Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(final ObservableEmitter<String> emitter) throws Exception {

                long sleepTime = getRandomNumber();
                Log.i(TAG, "Oservable1 : Sleep: " + sleepTime + " Thread: " + Thread.currentThread().getName());

                Thread.sleep(sleepTime);

                emitter.onNext( "From Observable1 Result" );
                emitter.onComplete();

            }
        })
                .subscribeOn(Schedulers.newThread() );
    }
});

可观察2:

Observable<String> observable2 =
        Observable.defer(new Callable<ObservableSource<? extends String>>() {
            @Override
            public ObservableSource<? extends String> call() throws Exception {
                return Observable.create(new ObservableOnSubscribe<String>() {
                    @Override
                    public void subscribe(final ObservableEmitter<String> emitter) throws Exception {

                        long sleepTime = getRandomNumber();
                        Log.i(TAG, "Oservable2 :  Sleep: " + sleepTime + " Thread: " + Thread.currentThread().getName());

                        Thread.sleep(sleepTime);

                        emitter.onNext("From Observable2 Result" );
                        emitter.onComplete();

                    }
                })
                        .subscribeOn(Schedulers.newThread());
            }
        });

getRandomNumber方法:

private long getRandomNumber() {
    return (long) (Math.random() * 100);
}

我正在创建一个随机延迟以返回String

ambArray:

    Observable.ambArray(observable1, observable2)
            .subscribeOn(Schedulers.io())
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Log.i(TAG, "Result : " + s);
                }
            });

这导致我java.lang.InterruptedException

当我从observables sleep删除ambArray时,工作正常。如果我手动创建一个新线程然后使用睡眠,这也可以正常工作。

使用手动线程重新编写Observable:

Observable<String> observable1 =
Observable.defer(new Callable<ObservableSource<? extends String>>() {
    @Override
    public ObservableSource<? extends String> call() throws Exception {
        return  Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(final ObservableEmitter<String> emitter) throws Exception {


                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        long sleepTime = getRandomNumber();
                        Log.i(TAG, "Oservable1 : Sleep: " + sleepTime + " Thread: " + Thread.currentThread().getName());
                        try {
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            Log.e(TAG, e.getMessage());
                        }
                        emitter.onNext( "From Observable1 Result" );
                        emitter.onComplete();
                    }
                }).start();


            }
        })
               /* .subscribeOn(Schedulers.newThread() )*/;
    }
});

如果我在两个可观察中以这种方式使用Thread,它可以正常工作。 为什么使用Schedulers线程导致Exception?为什么手动使用线程不会导致任何Exception?有什么区别?

修改

Logcat:

     W/System.err: java.lang.InterruptedException
     W/System.err:     at java.lang.Thread.sleep(Native Method)
     W/System.err:     at java.lang.Thread.sleep(Thread.java:1031)
     W/System.err:     at java.lang.Thread.sleep(Thread.java:985)
     W/System.err:     at com.yousuf.shawon.rxandroidsamples.fragments.AmdExampleFragment$5$1.subscribe(AmdExampleFragment.java:306)
     W/System.err:     at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40)
     W/System.err:     at io.reactivex.Observable.subscribe(Observable.java:11442)
     W/System.err:     at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
     W/System.err:     at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:571)
     W/System.err:     at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
     W/System.err:     at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
     W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
     W/System.err:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
     W/System.err:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
     W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
     W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
     W/System.err:     at java.lang.Thread.run(Thread.java:818)

1 个答案:

答案 0 :(得分:1)

使用Scheduler,后备线程池会记住哪个线程正在为休眠的方法提供服务,并且可以在取消时中断它。使用普通的Thread s,你的引用就会丢失,你还没有将它们连接到取消机制:

@Override
public void subscribe(final ObservableEmitter<String> emitter) throws Exception {
    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            long sleepTime = getRandomNumber();
            Log.i(TAG, "Oservable1 : Sleep: " + sleepTime + 
                  " Thread: " + Thread.currentThread().getName());
            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
                Log.e(TAG, e.getMessage());
            }
            emitter.onNext( "From Observable1 Result" );
            emitter.onComplete();
        }
    });
    t.start();
    emitter.setCancellable(() -> t.interrupt());
}