Java9反应流:一个订阅者是否属于一个发布者
我想知道,如果发布服务器正在停止运行(例如被关闭),被动流发布服务器是否可以安全地假定订阅只属于它,Java9反应流:一个订阅者是否属于一个发布者,java,reactive-programming,java-9,reactive,Java,Reactive Programming,Java 9,Reactive,我想知道,如果发布服务器正在停止运行(例如被关闭),被动流发布服务器是否可以安全地假定订阅只属于它,java.util.concurrent.Flow.Subscriber#onComplete。下面的代码示例演示了这一困境(显然,这只是一些演示问题的合成代码): import java.util.concurrent.ConcurrentLinkedQueue; 导入java.util.concurrent.Flow; 导入java.util.concurrent.ScheduledExecu
java.util.concurrent.Flow.Subscriber#onComplete
。下面的代码示例演示了这一困境(显然,这只是一些演示问题的合成代码):
import java.util.concurrent.ConcurrentLinkedQueue;
导入java.util.concurrent.Flow;
导入java.util.concurrent.ScheduledExecutorService;
导入java.util.concurrent.ScheduledThreadPoolExecutor;
导入java.util.concurrent.TimeUnit;
公共类TimePublisher实现Flow.Publisher{
私有最终ScheduledExecutorService ScheduledExecutorService=新ScheduledThreadPoolExecutor(1);
private final ConcurrentLinkedQueue订户的文档说
此接口中的方法按每个流的严格顺序调用。订阅
onComplete
特别是:
方法,当已知未因错误而终止的订阅不会发生其他订阅方方法调用时调用。在此之后,订阅不会调用任何其他订阅方方法。如果此方法引发异常,则结果行为未定义
因此,其他订阅继续调用方法是合法的
Flow
文档说明在一个订阅者中有多个订阅
s是可能的,但不建议:
由于对给定Flow.Subscription的订户方法调用是严格排序的,因此这些方法不需要使用锁或volatile,除非订户维护多个订阅(在这种情况下,最好定义多个订户,每个订户都有自己的订阅)
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Flow;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TimePublisher implements Flow.Publisher<Long> {
private final ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);
private final ConcurrentLinkedQueue<Flow.Subscriber<? super Long>> subscribersList = new ConcurrentLinkedQueue<>();
private TimePublisher() {
}
public static TimePublisher newInstance() {
TimePublisher timePublisher = new TimePublisher();
timePublisher.startTickScheduler();
return timePublisher;
}
private void startTickScheduler() {
scheduledExecutorService.scheduleAtFixedRate(() -> {
// does not make too much sense: just for the sake of the example
final long currentTimeMillis = System.currentTimeMillis();
subscribersList.forEach(sub -> sub.onNext(currentTimeMillis));
}, 1, 1, TimeUnit.SECONDS);
}
@Override
public void subscribe(Flow.Subscriber<? super Long> subscriber) {
subscribersList.add(subscriber);
subscriber.onSubscribe(new Flow.Subscription() {
@Override
public void request(long n) {
// no-op in this sample
}
@Override
public void cancel() {
subscribersList.remove(subscriber);
}
});
}
public void stop() {
// the publisher can be stopped from the outside: after that it will
// definitely not emit any next items.
scheduledExecutorService.shutdown();
// QUESTION: can we assume that a Subscriber is subscribed to only this Publisher?
// if it is subscribed to another publisher, the following is illegal, as onNext
// could potentially be called by another Publisher...
subscribersList.forEach(Flow.Subscriber::onComplete);
subscribersList.clear();
}
}