Spring 订阅UnicastProcessor从不触发
我希望在项目出现时对其进行批处理,因此我创建了一个UnicastProcessor,并像这样订阅了它Spring 订阅UnicastProcessor从不触发,spring,project-reactor,Spring,Project Reactor,我希望在项目出现时对其进行批处理,因此我创建了一个UnicastProcessor,并像这样订阅了它 UnicastProcessor<String> processor = UnicastProcessor.create() processor .bufferTimeout(10, Duration.ofMillis(500)) .subscribe(new Subscriber<List<String>>() {
UnicastProcessor<String> processor = UnicastProcessor.create()
processor
.bufferTimeout(10, Duration.ofMillis(500))
.subscribe(new Subscriber<List<String>>() {
@Override
public void onSubscribe(Subscription subscription) {
System.out.println("OnSubscribe");
}
@Override
public void onNext(List<String> strings) {
System.out.println("OnNext");
}
@Override
public void onError(Throwable throwable) {
System.out.println("OnError");
}
@Override
public void onComplete() {
System.out.println("OnComplete");
}
});
UnicastProcessor=UnicastProcessor.create()
处理器
.bufferTimeout(10,持续时间.百万(500))
.subscribe(新订户(){
@凌驾
认购时的公共作废(认购){
System.out.println(“OnSubscribe”);
}
@凌驾
public void onNext(列出字符串){
System.out.println(“OnNext”);
}
@凌驾
公共作废登记员(可丢弃){
System.out.println(“OnError”);
}
@凌驾
未完成的公共空间(){
System.out.println(“OnComplete”);
}
});
然后出于测试目的,我创建了一个新线程,并开始在循环中添加项
new Thread(() -> {
int limit = 100
i = 0
while(i < limit) {
++i
processor.sink().next("Hello $i")
}
System.out.println("Published all")
}).start()
新线程(()->{
整数极限=100
i=0
while(i
运行此操作(并让主线程休眠5秒钟)后,我可以看到所有项目都已发布,但订阅者不会触发任何事件,因此我无法处理任何已发布的项目
我做错了什么?反应流规范就是答案!
发布者向订阅者发送的onNext的总数
必须小于或等于请求的元素总数
由该认购人随时认购
在您的示例中,您只需提供一个在任何意义上都不做任何事情的订阅者。反过来,reactivestreams规范直接指出,如果您没有调用Subscription#request
方法,则不会发生任何事情(不会有onNext调用)
订阅者必须通过Subscription.request(长n)向用户发出请求信号
接收下一个信号
因此,要解决您的问题,可能的解决方案之一是以以下方式更改代码:
UnicastProcessor<String> processor = UnicastProcessor.create()
processor
.bufferTimeout(10, Duration.ofMillis(500))
.subscribe(new Subscriber<List<String>>() {
@Override
public void onSubscribe(Subscription subscription) {
System.out.println("OnSubscribe");
subscription.request(Long.MAX_VALUE);
}
@Override
public void onNext(List<String> strings) {
System.out.println("OnNext");
}
@Override
public void onError(Throwable throwable) {
System.out.println("OnError");
}
@Override
public void onComplete() {
System.out.println("OnComplete");
}
});
注意,在本例中,我执行了另一个方法
serialize
,该方法提供线程安全接收器,并确保同时调用FluxSink#next
不会导致违反ReactiveStreams规范。另一个问题:您还应该调用sink()
仅一次,并重用提供的FluxSink
而不是在循环中调用它。@SimonBaslé,从技术上讲,这是可能的,因为UnicastProcessor
在默认队列的情况下提供内部同步,但是是的。我会提到
UnicastProcessor<String> processor = UnicastProcessor.create()
FluxSink<String> sink = processor.serialize().sink();
...
new Thread(() -> {
int limit = 100
i = 0
while(i < limit) {
++i
sink.next("Hello $i")
}
System.out.println("Published all")
}).start()