SubmissionPublisher 不适合做响应式变量,因其面向多元素数据流,缺乏保存最新值、获取当前值、自动通知变更等能力,仅支持手动 submit 推送,且新订阅者无法获得历史值。

SubmissionPublisher 是 Java 9 引入的 java.util.concurrent.Flow 中的一个具体实现类,用于发布(publish)数据流,但它本身不直接支持响应式变量(即动态变化、可观察的单个值)的发布订阅。它面向的是“多元素、有生命周期”的数据流(类似 Reactive Streams 的 Publisher<t></t>),而非类似 RxJava 的 BehaviorSubject 或 Reactor 的 Mono<t></t> / AtomicReference<t></t> + 监听器这类“响应式变量”场景。
为什么 SubmissionPublisher 不适合做“响应式变量”
SubmissionPublisher 的设计目标是:
- 支持背压(通过
Subscription.request()) - 异步、线程安全地批量提交多个元素(
submit(T item)) - 配合
Flow.Subscriber实现标准响应式流协议(onSubscribe/onNext/onError/onComplete)
它没有内置机制来:
- 保存并分发“最新值”给新订阅者(即无状态快照)
- 暴露当前值(get())或设置新值(set())
- 在值变更时自动通知所有活跃订阅者(除非你手动调用 submit)
- 新订阅者不会收到历史值(除非你在 subscribe 时主动调用
subscriber.onNext(latest)) - 若需“热发布+初始值回放”,需在
subscribe中先触发一次onNext(latest)(但要确保线程安全与订阅时序) - 背压对单值变量意义不大,可考虑用
new SubmissionPublisher(null, 0)禁用缓冲 -
Reactor:用
AtomicReference<t></t>+Flux.create()或DirectProcessor(已弃用)→ 推荐Sinks.Many<t>.multicast().onBackpressureBuffer()</t> -
RxJava:用
BehaviorSubject.createDefault(initial)或AtomicReference<t></t>配合Subject -
Java 标准库轻量级:自定义
Property<t></t>类,内部用CopyOnWriteArrayList存监听器,配合set(T)触发回调(无背压,简单高效)
如何用 SubmissionPublisher 模拟响应式变量行为
若坚持使用 SubmissionPublisher 实现类似“响应式变量”的效果,需额外封装。核心思路是:每次变量更新时显式 submit,并让订阅者自行缓存最新值。
示例(简易封装):
public final class ReactiveVar<T> {
private final SubmissionPublisher<T> publisher = new SubmissionPublisher<>();
private volatile T latest;
public void set(T value) {
this.latest = value;
publisher.submit(value); // 主动推送
}
public T get() {
return latest;
}
public void subscribe(Flow.Subscriber<? super T> subscriber) {
publisher.subscribe(subscriber);
}
public void close() {
publisher.close();
}
}
⚠️ 注意:
更合适的替代方案
对于真正的响应式变量(如 UI 状态、配置热更新),推荐以下更自然的工具:
总结
SubmissionPublisher 是为“流”而生,不是为“变量”设计。强行用它模拟响应式变量可行,但需手动管理状态、初始值、线程安全和订阅时机,容易出错且违背其设计本意。真正需要响应式变量时,优先选用语义明确、生态成熟的响应式库抽象,或手写轻量监听器模型——简洁、可控、不易误用。

















