代码适用于RX Completable而不阻塞onSubscribe线程

时间:2017-10-06 22:12:47

标签: java multithreading rx-java scheduler rx-android

我有一些传统的非RX代码通过生成一个新线程来完成一些网络工作。 当工作完成时,它会在回调上调用一个方法。

我无法控制此代码运行的线程。这是遗产,它本身会产生一个新的Thread

这可以简化为:

interface Callback {
    void onSuccess();
}

static void executeRequest(String name, Callback callback) {
    new Thread(() -> {
        try {
            System.out.println(" Starting... " + name);
            Thread.sleep(2000);
            System.out.println(" Finishing... " + name);
            callback.onSuccess();
        } catch (InterruptedException ignored) {}
    }).start();
}

我想将其转换为RX Completable。为此,我使用Completable#create()CompletableEmitter的实现调用executeRequest传递Callback的实现,该请求在请求完成时发出信号。

订阅时我还会打印日志跟踪以帮助我调试。

static Completable createRequestCompletable(String name) {
        return Completable.create(e -> executeRequest(name, e::onComplete))
                .doOnSubscribe(d -> System.out.println("Subscribed to " + name));
}

这可以按预期工作。 Completable仅在“请求”完成并且调用回调之后才完成。

问题是,当在trampoline调度程序中订阅这些补充表时,它不会在订阅第二个请求之前等待第一个请求完成。

此代码:

final Completable c1 = createRequestCompletable("1");
c1.subscribeOn(Schedulers.trampoline()).subscribe();

final Completable c2 = createRequestCompletable("2");
c2.subscribeOn(Schedulers.trampoline()).subscribe();

输出:

Subscribed to 1
    Starting... 1 
Subscribed to 2
    Starting... 2 
    Finishing... 1 
    Finishing... 2

如您所见,即使我正在订阅Completable,它也会在第一个Completable完成之前订阅第二个trampoline

我想排队completables,以便第二个等待第一个完成,输出:

Subscribed to 1
    Starting... 1 
    Finishing... 1
Subscribed to 2
    Starting... 2  
    Finishing... 2

我确定问题与工作线程中的工作有关。如果Completable的实现没有生成新线程,它将按预期工作。 但这是遗留代码,而我正在尝试做的是将其调整为RX而不进行修改。

注意:请求在程序的不同点执行 - 我不能使用andThenconcat来实现序列化执行。

1 个答案:

答案 0 :(得分:1)

我设法通过使用Completables明确阻止订阅Thread来顺序执行Latch。 但我不认为这是在RX中这样做的惯用方法,我仍然不明白为什么我需要这样做,并且在Completable完成之前线程不会被阻止。

static Completable createRequestCompletable(String name) {
    final CountDownLatch latch = new CountDownLatch(1);
    return Completable.create(e -> {
        executeRequest(name, () -> {
            e.onComplete();
            latch.countDown();
        });
        latch.await();
    })
    .doOnSubscribe(disposable -> System.out.println("Subscribed to " + name));
}