RX Java缓冲区丢失项目

时间:2018-10-27 13:11:52

标签: java rx-java rx-java2 reactive

我有一个具有以下配置的PublishSubject:

PublishSubject<Message> messageObserver = 
    messageObserver
    .filter(t -> test(t))
    .buffer(eventsSaveTimeSpanInSeconds, TimeUnit.SECONDS, eventsSaveCount)
    .subscribe(messages -> saveToDB(messages));

我的应用程序的不同线程正在通过PublishSubject向此onNext()写消息。

如我所见,底层buffer的{​​{1}}是非线程安全的,因为其onNext如下所示:

ObservableBufferTimed.BufferExactBoundedObserver

为了使比赛情况更加明显,我将public void onNext(T t) { U b; synchronized (this) { b = buffer; if (b == null) { return; } b.add(t); if (b.size() < maxSize) { return; } buffer = null; producerIndex++; } if (restartTimerOnMaxSize) { timer.dispose(); } fastPathOrderedEmit(b, false, this); try { b = ObjectHelper.requireNonNull(bufferSupplier.call(), "The buffer supplied is null"); } catch (Throwable e) { Exceptions.throwIfFatal(e); actual.onError(e); dispose(); return; } synchronized (this) { buffer = b; consumerIndex++; } if (restartTimerOnMaxSize) { timer = w.schedulePeriodically(this, timespan, timespan, unit); } } eventsSaveTimeSpanInSeconds参数设置为1(1秒内发生1个事件)。

问题出现在此块中:

eventsSaveCount

因此,如果两个消息同时在缓冲,则第一个消息将填充synchronized (this) { b = buffer; if (b == null) { return; } b.add(t); if (b.size() < maxSize) { return; } buffer = null; producerIndex++; } 并将空值分配给缓冲区变量。新缓冲区将在同步块之后稍后初始化。如果存在竞争条件,则buffer为null时,由于以下代码,第二条消息将不会被缓冲:

buffer

这是缺陷还是错误的缓冲区行为?如何避免这种情况?

1 个答案:

答案 0 :(得分:0)

如果多个线程要调用onNext,请使用序列化的主题:

Subject<Message> messageObserver = PublishSubject.<Message>create().toSerialized();

messageObserver
.filter(t -> test(t))
.buffer(eventsSaveTimeSpanInSeconds, TimeUnit.SECONDS, eventsSaveCount)
.subscribe(messages -> saveToDB(messages));

// from any thread now
messageObserver.onNext(message);