我想知道被动流发布者是否可以安全地假设订阅仅属于它 ,并且如果发布者即将退出使用(例如被关闭),请致电java.util.concurrent.Flow.Subscriber#onComplete
。下面的代码示例演示了难题(显然,这只是一些综合代码来演示问题):
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();
}
}
TimePublisher#stop
时,该特定的发布者将绝对不会发出任何onNext
调用,因此调用onComplete
似乎是合理的选择onComplete
可能是非法的,因为另一个发布者可能仍在发出项目。答案 0 :(得分:3)
Subscriber
的文档中说
对于每个Flow.Subscription ,该接口中的方法均按严格的顺序调用。
onComplete
,尤其是:
在已知不会因错误终止的订阅不会发生其他订阅者方法调用的情况下调用
方法,此后,订阅不会调用其他订阅者方法。如果此方法引发异常,则导致的行为是不确定的。
因此其他Subscription
继续调用方法是合法的。
Flow
文档说,在Subscription
实现中可以有多个Subscriber
,但不建议这样做:
由于给定Flow的Subscriber方法调用是严格排序的,因此除非这些Subscriber维护多个Subscriptions(在这种情况下最好定义多个Subscriber,最好使用多个Subscriber,否则不需要使用这些方法来使用锁或volatile)自己的订阅)。