RxJava:使用SubscribeOn使程序退出而不完成

时间:2017-01-25 12:31:49

标签: java rx-java reactive-programming rx-java2

这是我的示例代码

Observable.range(1,5)
            .subscribeOn(Schedulers.computation())
            .map(Observables05::doSomething)
            .subscribe(System.out::println, Throwable::printStackTrace, () -> System.out.println("done"));

我的doSomething方法是,

public static int doSomething(int i) {
    try {
        System.out.println("Processing " + i +
                " on Thread -- " + Thread.currentThread().getName());
        Thread.sleep(500);
        return i;
    } catch (InterruptedException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}

仅使用主线程中的示例代码退出程序。但是,如果在此之后使用Thread.sleep(3000),则程序在睡眠时间结束时退出之前正常工作。

这是预期的行为吗?为什么?如何在不使用Thread.sleep的情况下运行此代码?

3 个答案:

答案 0 :(得分:3)

subscribeOn安排subscribe调用后台线程(您选择了computation调度程序)。在此计划之后,您的主线程可以自由运行,即终止您的程序。

不知何故,您需要等待所有理想的任务完成才能退出。 Thread.sleep(3000)为简单的测试用例完成工作。

真正的程序通常不会那么快地终止。仍然存在需要等待某个后台任务完成的情况。您可以使用各种线程同步机制(例如CountDownLatch)。

答案 1 :(得分:0)

如果您想测试您编写的代码,请使用TestSubscriber

代码看起来像这样:

TestSubscriber<Integer> testSubscriber = new TestSubscriber<>();

Observable.range(1,5)
        .subscribeOn(Schedulers.computation())
        .map(Observables05::doSomething)
        .subscribe(testSubscriber);

testSubscriber.awaitTerminalEvent(10, TimeUnit.SECONDS);

请记住,TestSubscriber允许您测试的不仅仅是终端事件。

答案 2 :(得分:0)

这是预期的行为。您在main方法中执行时的简单解决方案是在订阅之前使用toBlocking() - 如下所示 -

    Observable.range(1,5)
    .subscribeOn(Schedulers.computation())
    .map(DummyJunk::doSomething)
    .toBlocking()
    .subscribe(System.out::println, Throwable::printStackTrace, () -> System.out.println("done"));