BehaviorSubject订阅另一个线程

时间:2019-01-06 10:37:21

标签: java reactive-programming rx-java2

我是RxJava的新手,所以选择使用它,因为我认为它非常适合我的用例。

我想在无限的时间内观察到一些Integer值。每当这些值之一发生变化(即事件)时,我都希望在另一个线程上调用其所有观察者。

由于观察时间长,我以为我需要使用BehaviorSubject类(尽管起初我以为Observable是我所需要的..看到我只需要“观察”) ,我可以使用subscribeOn()方法来设置调度程序,从而实现在后台线程上调用订阅者:

private BehaviorSubject<Integer> rotationPositionSubject = BehaviorSubject.createDefault(getRotorPosition());
rotationPositionSubject.subscribeOn(scheduler);

我有一个rotate()方法,用于更新rotationPositionSubject,它将从主线程调用:

@Override
public synchronized int rotate()
{
    final int newRotorPosition = super.rotate();
    rotationPositionSubject.onNext(newRotorPosition);

    return newRotorPosition;
}

但是,通过上面的代码,我发现订户是在“主”线程上调用的。检查subscribeOn()的文档:

  

返回:

     

修改了源ObservableSource,以便其订阅发生在指定的Scheduler上

由于我没有使用返回的ObservableSource,所以上面的代码无法工作,但是返回对象是Observable,对我的应用程序没有用?

然后的问题是,如何使用RxJava长期观察任何对象并在后台线程上调用订阅服务器,或者RxJava是错误的选择?

1 个答案:

答案 0 :(得分:0)

经过一番试验,似乎在使用 public static void streamingDataOperations(ClientSocket cs) throws InterruptedException, IOException{ // call - retrieve streaming data constantly from client server, // and write a line in the csv file at a rate of 150 milliseconds // using bufferedWriter and printWriter (print method). // Note that the flush method of bufferedWriter is never called, // I would assume the data is in fact being written in buffered memory // not the actual file. cs.reqStreamingData(output_file); // <- this method comes from client's API. // I would like to another thread (aka data processing thread) which repeats itself every 15 minutes. // I am aware I can do that by creating a class that extends TimeTask and fix a schedule // Now when this thread runs, there are things I want to do. // 1. flush last 15 minutes of data to the output_file (Note no synchronized statement method or statements are used here, hence no object is being locked.) // 2. process the data in R // 3. wait for the output in R to come back // 4. clear file contents, so that it always store data that only occurs in the last 15 minutes } 对象时需要格外小心,而且它们的用法并不像我从各种接口的名称推断出的那样明显。

作为证明我目前正在做的测试方法:

BehaviorSubject

这将导致不希望的结果:

  

对线程ID执行测试:1
  在线程ID上调用onSubscribe():1
  在线程ID上调用onNext():1
  在线程ID上调用onNext():1

     

以退出代码0结束的过程

(不需要,因为在主线程上调用了@Test public void test() { System.out.println("Executing test on thread ID: " + Thread.currentThread().getId()); final BehaviorSubject<Integer> rotorBehaviour = BehaviorSubject.create(); rotorBehaviour.subscribeOn(Schedulers.single()); rotorBehaviour.subscribe(new Observer<Integer>() { @Override public void onSubscribe(final Disposable d) { System.out.println("onSubscribe() called on thread ID: " + Thread.currentThread().getId()); } @Override public void onNext(final Integer integer) { System.out.println("onNext() called on thread ID: " + Thread.currentThread().getId()); } @Override public void onError(final Throwable e) { System.out.println("onError() called on thread ID: " + Thread.currentThread().getId()); } @Override public void onComplete() { System.out.println("onComplete() called on thread ID: " + Thread.currentThread().getId()); } }); rotorBehaviour.onNext(1); rotorBehaviour.onNext(2); }

修改代码以使用从调用onNext()返回的Observable会得到相同的不良结果:

subscribeOn

结果:

  

对线程ID执行测试:1
  在线程ID上调用onSubscribe():1
  在线程ID上调用onNext():1
  在线程ID上调用onNext():1

     

以退出代码0结束的过程

但是使用@Test public void test() { System.out.println("Executing test on thread ID: " + Thread.currentThread().getId()); final BehaviorSubject<Integer> rotorBehaviour = BehaviorSubject.create(); Observable<Integer> rotorObservable = rotorBehaviour.subscribeOn(Schedulers.single()); rotorObservable.subscribe(new Observer<Integer>() { @Override public void onSubscribe(final Disposable d) { System.out.println("onSubscribe() called on thread ID: " + Thread.currentThread().getId()); } @Override public void onNext(final Integer integer) { System.out.println("onNext() called on thread ID: " + Thread.currentThread().getId()); } @Override public void onError(final Throwable e) { System.out.println("onError() called on thread ID: " + Thread.currentThread().getId()); } @Override public void onComplete() { System.out.println("onComplete() called on thread ID: " + Thread.currentThread().getId()); } }); rotorBehaviour.onNext(1); rotorBehaviour.onNext(2); } 方法确实可以达到预期的结果:

observeOn()
  

对线程ID执行测试:1
  在线程ID上调用onSubscribe():1
   onNext()调用了线程ID:13
   onNext()调用了线程ID:13

     

以退出代码0结束的过程

在所有示例中,我仍然使用@Test public void test() { System.out.println("Executing test on thread ID: " + Thread.currentThread().getId()); final BehaviorSubject<Integer> rotorBehaviour = BehaviorSubject.create(); Observable<Integer>rotorObservable = rotorBehaviour.observeOn(Schedulers.single()); rotorObservable.subscribe(new Observer<Integer>() { @Override public void onSubscribe(final Disposable d) { System.out.println("onSubscribe() called on thread ID: " + Thread.currentThread().getId()); } @Override public void onNext(final Integer integer) { System.out.println("onNext() called on thread ID: " + Thread.currentThread().getId()); } @Override public void onError(final Throwable e) { System.out.println("onError() called on thread ID: " + Thread.currentThread().getId()); } @Override public void onComplete() { System.out.println("onComplete() called on thread ID: " + Thread.currentThread().getId()); } }); rotorBehaviour.onNext(1); rotorBehaviour.onNext(2); } 对象来发起事件,并且我只是偶然发现这将提供期望的结果。

让我担心的是,我可能以不正确的方式使用BehaviorSubjectObservable,只是“碰巧”会给我正确的结果,即在后台线程上调用了订阅者。除非我在文档中的某个地方错过了它,否则如何使用这些对象来获得期望的结果似乎并不明显。