FlowableProcessor详解
- 一、概述
- 二、PublishProcessor(实时发布处理器)
- 三、BehaviorProcessor(行为处理器)
- 四、ReplayProcessor(重放处理器)
- 五、UnicastProcessor(单播处理器)
一、概述
核心概念:
FlowableProcessor 是支持背压的 Subject,它同时实现了:
- Processor<T, R> 接口(Reactive Streams 规范)
- Flowable 接口(可以被订阅)
- FlowableSubscriber 接口(可以订阅其他Flowable)
继承关系:
java
// 核心继承关系
public abstract class FlowableProcessor<T>
extends Flowable<T>
implements Processor<T, T>, FlowableSubscriber<T> {
// 核心方法
public abstract boolean hasSubscribers();
public abstract Throwable getThrowable();
public abstract boolean hasThrowable();
public abstract boolean hasComplete();
public abstract boolean hasSubscribers();
}
与Subject对比:
| 特性 | FlowableProcessor | Subject |
|---|---|---|
背压支持 |
✅ 完全支持 | ❌ 不支持(Observable版本) |
Reactive Streams兼容 |
✅ Processor接口 | ❌ 不兼容 |
订阅者数量限制 |
可配置 | 无限制 |
缓冲区策略 |
多种策略 | 无缓冲区 |
性能开销 |
较高 | 较低 |
二、PublishProcessor(实时发布处理器)
2.1、核心特性
- 类似 PublishSubject,但支持背压
- 只向当前订阅者发射数据
- 不缓存任何数据
- 支持背压策略
java
@Test
public void testPublishProcessor() {
//基本用法
PublishProcessor<Integer> processor = PublishProcessor.create();
//生产者
Flowable.range(1, 1000)
.subscribe(processor);
//消费者1
processor.onBackpressureBuffer(100)//缓冲区大小
.subscribe(
data -> System.out.println("Consumer 1:" + data),
error -> System.out.println("Error 1:" + error),
() -> System.out.println("Completed 1")
);
//消费者2(稍后订阅,收不到之前的数据)
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
processor.subscribe(
data -> System.out.println("Consumer 2:" + data),
error -> System.out.println("Error 2:" + error),
() -> System.out.println("Completed 2")
);
}
背压处理示例:
java
public class PublishProcessorBackpressure {
public static void demoBackpressure() {
PublishProcessor<Integer> processor = PublishProcessor.create();
// 快速生产者
Flowable.interval(10, TimeUnit.MILLISECONDS)
.take(1000)
.map(Long::intValue)
.subscribe(processor);
// 慢速消费者
processor
.onBackpressureBuffer(
50, // 缓冲区大小
() -> System.out.println("Buffer overflow"),
BackpressureOverflowStrategy.DROP_OLDEST
)
.observeOn(Schedulers.io(), false, 16) // 缓冲区16
.subscribe(
data -> {
// 慢速处理
Thread.sleep(100);
System.out.println("Processed: " + data);
},
error -> System.err.println("Error: " + error)
);
}
// 使用不同的背压策略
public static void differentStrategies() {
PublishProcessor<Integer> processor = PublishProcessor.create();
// 策略1: BUFFER - 无限缓冲(可能OOM)
processor.onBackpressureBuffer();
// 策略2: DROP - 丢弃溢出数据
processor.onBackpressureDrop(dropped ->
System.out.println("Dropped: " + dropped)
);
// 策略3: LATEST - 保留最新数据
processor.onBackpressureLatest();
// 策略4: ERROR - 缓冲区满时抛异常
processor.onBackpressureBuffer(100,
() -> {},
BackpressureOverflowStrategy.ERROR
);
}
}
2.2、使用场景
java
// 1. 实时数据流处理
public class RealTimeDataProcessor {
private final PublishProcessor<SensorData> dataProcessor = PublishProcessor.create();
private final CompositeDisposable disposables = new CompositeDisposable();
public RealTimeDataProcessor() {
// 设置数据处理管道
disposables.add(
dataProcessor
.onBackpressureBuffer(1000)
.observeOn(Schedulers.computation())
.subscribe(this::processData)
);
}
public void feedData(SensorData data) {
dataProcessor.onNext(data);
}
public void addConsumer(Consumer<SensorData> consumer) {
disposables.add(
dataProcessor
.onBackpressureBuffer(100)
.subscribe(consumer::accept)
);
}
private void processData(SensorData data) {
// 复杂的数据处理逻辑
}
}
// 2. 事件总线(支持背压)
public class BackpressureEventBus {
private final PublishProcessor<Event> eventProcessor = PublishProcessor.create();
public void postEvent(Event event) {
eventProcessor.onNext(event);
}
public Flowable<Event> getEventStream() {
return eventProcessor
.onBackpressureBuffer(1000)
.filter(event -> event != null)
.share(); // 多播
}
public Flowable<Event> getEventStream(String eventType) {
return getEventStream()
.filter(event -> event.getType().equals(eventType));
}
}
// 3. 消息队列桥接
public class MessageQueueBridge {
private final PublishProcessor<Message> messageProcessor = PublishProcessor.create();
private final MessageQueue queue;
public MessageQueueBridge(MessageQueue queue) {
this.queue = queue;
// 从队列消费
Flowable.generate(
() -> queue.createConsumer(),
(consumer, emitter) -> {
Message msg = consumer.receive(1000, TimeUnit.MILLISECONDS);
if (msg != null) {
emitter.onNext(msg);
} else {
emitter.onComplete();
}
},
Consumer::close
)
.subscribe(messageProcessor);
}
public void sendMessage(Message message) {
messageProcessor.onNext(message);
}
public Flowable<Message> getMessageStream() {
return messageProcessor
.onBackpressureBuffer(100)
.doOnNext(msg -> queue.acknowledge(msg.getId()));
}
}
三、BehaviorProcessor(行为处理器)
3.1、核心特性
- 类似 BehaviorSubject,但支持背压
- 发射最近的一个值和后续值
- 需要初始值(或默认值)
- 支持背压策略
java
@Test
public void testBehaviorProcessor() {
//基本用法
BehaviorProcessor<String> processor = BehaviorProcessor.createDefault("Initial");
//订阅者1
processor.subscribe(data -> System.out.println("Subscriber 1:" + data));
processor.onNext("Update 1");
processor.onNext("Update 2");
//订阅者2(立即受到最近的值update 2)
processor.subscribe(data -> System.out.println("Subscriber 2:" + data));
processor.onNext("Update 3");
processor.onComplete();
//获取当前值
String currentValue = processor.getValue();
}
Subscriber 1:Initial
Subscriber 1:Update 1
Subscriber 1:Update 2
Subscriber 2:Update 2
Subscriber 1:Update 3
Subscriber 2:Update 3
背压处理示例:
java
public class BehaviorProcessorBackpressure {
public static void demoWithBackpressure() {
BehaviorProcessor<Integer> processor = BehaviorProcessor.create();
// 快速生产者
Flowable.interval(1, TimeUnit.MILLISECONDS)
.take(10000)
.map(Long::intValue)
.subscribe(processor);
// 慢速消费者
processor
.onBackpressureBuffer(
100,
() -> System.out.println("Buffer overflow"),
BackpressureOverflowStrategy.DROP_OLDEST
)
.observeOn(Schedulers.io(), false, 16)
.subscribe(
value -> {
Thread.sleep(10); // 慢速处理
System.out.println("Processed: " + value);
}
);
}
// 状态管理示例
public static class StateManager<T> {
private final BehaviorProcessor<T> stateProcessor;
private final Flowable<T> stateStream;
public StateManager(T initialState) {
this.stateProcessor = BehaviorProcessor.createDefault(initialState);
this.stateStream = stateProcessor
.onBackpressureLatest() // 状态只需要最新值
.distinctUntilChanged()
.share();
}
public void setState(T newState) {
stateProcessor.onNext(newState);
}
public Flowable<T> getStateStream() {
return stateStream;
}
public T getCurrentState() {
return stateProcessor.getValue();
}
public boolean hasState() {
return stateProcessor.hasValue();
}
}
}
3.2、使用场景
java
// 1. 应用状态管理
public class AppStateManager {
private final BehaviorProcessor<AppState> stateProcessor =
BehaviorProcessor.createDefault(AppState.IDLE);
private final Flowable<AppState> stateStream;
public AppStateManager() {
this.stateStream = stateProcessor
.onBackpressureLatest()
.distinctUntilChanged()
.share();
}
public void transitionTo(AppState newState) {
if (isValidTransition(stateProcessor.getValue(), newState)) {
stateProcessor.onNext(newState);
} else {
throw new IllegalStateException("Invalid state transition");
}
}
public Flowable<AppState> getStateStream() {
return stateStream;
}
public AppState getCurrentState() {
return stateProcessor.getValue();
}
public Flowable<Boolean> isState(AppState targetState) {
return stateStream.map(state -> state == targetState);
}
}
// 2. 配置管理
public class ConfigManager {
private final BehaviorProcessor<Config> configProcessor =
BehaviorProcessor.create();
private final Flowable<Config> configStream;
public ConfigManager(Config initialConfig) {
configProcessor.onNext(initialConfig);
this.configStream = configProcessor
.onBackpressureLatest()
.share();
}
public void updateConfig(Config newConfig) {
configProcessor.onNext(newConfig);
}
public Flowable<Config> getConfigStream() {
return configStream;
}
public Config getCurrentConfig() {
return configProcessor.getValue();
}
public <T> Flowable<T> observeConfigValue(
Function<Config, T> extractor,
Class<T> type
) {
return configStream
.map(extractor)
.distinctUntilChanged()
.filter(Objects::nonNull);
}
}
// 3. 实时价格更新
public class StockPriceFeed {
private final BehaviorProcessor<StockPrice> priceProcessor =
BehaviorProcessor.create();
private final Map<String, Flowable<Double>> symbolStreams = new ConcurrentHashMap<>();
public void updatePrice(String symbol, double price) {
priceProcessor.onNext(new StockPrice(symbol, price, System.currentTimeMillis()));
}
public Flowable<Double> getPriceStream(String symbol) {
return symbolStreams.computeIfAbsent(symbol, sym ->
priceProcessor
.onBackpressureLatest()
.filter(p -> p.getSymbol().equals(sym))
.map(StockPrice::getPrice)
.distinctUntilChanged()
.share()
);
}
public Double getCurrentPrice(String symbol) {
StockPrice current = priceProcessor.getValue();
if (current != null && current.getSymbol().equals(symbol)) {
return current.getPrice();
}
return null;
}
}
四、ReplayProcessor(重放处理器)
4.1、核心特性
- 类似 ReplaySubject,但支持背压
- 缓存所有发射的数据
- 可配置缓冲区大小和时间窗口
- 新订阅者立即收到所有缓存数据
java
@Test
public void testReplayProcessor() throws InterruptedException {
// 1. 无限缓存
ReplayProcessor<String> unlimited = ReplayProcessor.create();
unlimited.onNext("Data 1");
unlimited.onNext("Data 2");
unlimited.subscribe(data -> System.out.println("Subscriber: " + data));
// 输出: Data 1, Data 2
// 2. 限制缓存大小
ReplayProcessor<Integer> sizeLimited = ReplayProcessor.create(2);
sizeLimited.onNext(1);
sizeLimited.onNext(2);
sizeLimited.onNext(3); // 1被丢弃
sizeLimited.subscribe(System.out::println);
// 输出: 2, 3
// 3. 限制时间窗口
ReplayProcessor<String> timeLimited = ReplayProcessor.createWithTime(
1, TimeUnit.SECONDS, Schedulers.computation()
);
timeLimited.onNext("Data 1");
Thread.sleep(500);
timeLimited.onNext("Data 2");
Thread.sleep(600); // Data 1过期
timeLimited.subscribe(System.out::println);
// 输出: Data 2
// 4. 限制大小和时间
ReplayProcessor<String> bounded = ReplayProcessor.createWithTimeAndSize(
1, TimeUnit.SECONDS, // 时间窗口
Schedulers.computation(), // 最大缓存数量
100
);
}
Subscriber: Data 1
Subscriber: Data 2
1
2
3
Data 2
背压处理示例:
java
public class ReplayProcessorBackpressure {
public static void demoWithBackpressure() {
// 创建有界重放处理器
ReplayProcessor<Integer> processor = ReplayProcessor.createWithSize(1000);
// 快速生产者
Flowable.interval(1, TimeUnit.MILLISECONDS)
.take(10000)
.map(Long::intValue)
.subscribe(processor);
// 慢速消费者
processor
.onBackpressureBuffer(100)
.observeOn(Schedulers.io(), false, 16)
.subscribe(
value -> {
Thread.sleep(10);
System.out.println("Processed: " + value);
}
);
// 新订阅者会收到最近1000个值
Thread.sleep(1000);
processor.subscribe(value ->
System.out.println("New subscriber: " + value)
);
}
// 历史数据查询
public static class HistoricalDataStore<T> {
private final ReplayProcessor<T> dataProcessor;
private final Flowable<T> liveStream;
public HistoricalDataStore(int historySize) {
this.dataProcessor = ReplayProcessor.createWithSize(historySize);
this.liveStream = dataProcessor
.onBackpressureBuffer(100)
.share();
}
public void addData(T data) {
dataProcessor.onNext(data);
}
public Flowable<T> getLiveStream() {
return liveStream;
}
public Flowable<T> getHistory() {
return dataProcessor.take(dataProcessor.getBufferSize());
}
public Flowable<T> getRecentData(int count) {
return dataProcessor.takeLast(count);
}
public int getStoredCount() {
return dataProcessor.getBufferSize();
}
}
}
4.2、使用场景
java
// 1. 日志记录系统
public class LoggingSystem {
private final ReplayProcessor<LogEntry> logProcessor =
ReplayProcessor.createWithTime(1, TimeUnit.HOURS, Schedulers.io());
private final Flowable<LogEntry> logStream;
public LoggingSystem() {
this.logStream = logProcessor
.onBackpressureBuffer(10000)
.share();
}
public void log(Level level, String message, Throwable throwable) {
LogEntry entry = new LogEntry(
level,
message,
System.currentTimeMillis(),
Thread.currentThread().getName(),
throwable
);
logProcessor.onNext(entry);
}
public Flowable<LogEntry> getLogStream() {
return logStream;
}
public Flowable<LogEntry> getLogsByLevel(Level level) {
return logStream.filter(entry -> entry.getLevel() == level);
}
public Flowable<LogEntry> getRecentLogs(int count) {
return logProcessor.takeLast(count);
}
public Flowable<LogEntry> getLogsSince(long timestamp) {
return logStream.filter(entry -> entry.getTimestamp() >= timestamp);
}
}
// 2. 传感器数据历史
public class SensorDataRecorder {
private final ReplayProcessor<SensorData> dataProcessor =
ReplayProcessor.createWithTimeAndSize(
10, TimeUnit.MINUTES,
10000,
Schedulers.computation()
);
private final Flowable<SensorData> dataStream;
public SensorDataRecorder() {
this.dataStream = dataProcessor
.onBackpressureBuffer(1000)
.share();
}
public void recordData(SensorData data) {
dataProcessor.onNext(data);
}
public Flowable<SensorData> getDataStream() {
return dataStream;
}
public Flowable<SensorData> getDataBySensor(String sensorId) {
return dataStream.filter(data -> data.getSensorId().equals(sensorId));
}
public Flowable<Double> getAverageValue(String sensorId, long duration, TimeUnit unit) {
long window = System.currentTimeMillis() - unit.toMillis(duration);
return dataStream
.filter(data ->
data.getSensorId().equals(sensorId) &&
data.getTimestamp() >= window
)
.map(SensorData::getValue)
.reduce(0.0, (sum, val) -> sum + val)
.toFlowable()
.flatMap(sum ->
dataStream
.filter(data ->
data.getSensorId().equals(sensorId) &&
data.getTimestamp() >= window
)
.count()
.map(count -> count > 0 ? sum / count : 0.0)
);
}
}
// 3. 聊天消息历史
public class ChatRoom {
private final ReplayProcessor<Message> messageProcessor =
ReplayProcessor.createWithSize(1000);
private final Flowable<Message> messageStream;
public ChatRoom() {
this.messageStream = messageProcessor
.onBackpressureBuffer(100)
.share();
}
public void sendMessage(User sender, String content) {
Message message = new Message(
sender,
content,
System.currentTimeMillis()
);
messageProcessor.onNext(message);
}
public Flowable<Message> getMessageStream() {
return messageStream;
}
public Flowable<Message> getMessagesByUser(User user) {
return messageStream.filter(msg -> msg.getSender().equals(user));
}
public void replayHistoryFor(User user, int messageCount) {
messageProcessor
.takeLast(messageCount)
.subscribe(msg -> sendToUser(user, msg));
}
}
五、UnicastProcessor(单播处理器)
5.1、核心特性
- 类似 UnicastSubject,但支持背压
- 只允许一个订阅者
- 支持缓冲区
- 如果没有订阅者,会缓存数据直到有订阅者
java
// 基本用法
UnicastProcessor<String> processor = UnicastProcessor.create();
// 发射数据(还没有订阅者,数据被缓存)
processor.onNext("Cached 1");
processor.onNext("Cached 2");
// 订阅者(立即收到缓存的数据)
processor.subscribe(
data -> System.out.println("Received: " + data),
error -> System.err.println("Error: " + error),
() -> System.out.println("Completed")
);
processor.onNext("Live 1");
processor.onComplete();
// 输出:
// Received: Cached 1
// Received: Cached 2
// Received: Live 1
// Completed
// 尝试第二个订阅者会抛异常
try {
processor.subscribe(data -> System.out.println("Second: " + data));
} catch (IllegalStateException e) {
System.out.println("只能有一个订阅者: " + e.getMessage());
}
背压处理示例:
java
public class UnicastProcessorBackpressure {
public static void demoWithBackpressure() {
// 创建带缓冲区的单播处理器
UnicastProcessor<Integer> processor = UnicastProcessor.create(100);
// 快速生产者
Flowable.interval(1, TimeUnit.MILLISECONDS)
.take(1000)
.map(Long::intValue)
.subscribe(processor);
// 慢速消费者
processor
.onBackpressureBuffer(50)
.observeOn(Schedulers.io(), false, 16)
.subscribe(
value -> {
Thread.sleep(10);
System.out.println("Processed: " + value);
}
);
}
// 队列式处理器
public static class QueueProcessor<T> {
private final UnicastProcessor<T> processor;
private final Flowable<T> outputStream;
public QueueProcessor(int bufferSize) {
this.processor = UnicastProcessor.create(bufferSize);
this.outputStream = processor
.onBackpressureBuffer(bufferSize)
.share();
}
public void enqueue(T item) {
processor.onNext(item);
}
public void complete() {
processor.onComplete();
}
public void error(Throwable throwable) {
processor.onError(throwable);
}
public Flowable<T> getOutputStream() {
return outputStream;
}
public boolean hasSubscriber() {
return processor.hasSubscribers();
}
public int getBufferSize() {
return processor.getBufferSize();
}
}
}
5.2、使用场景
java
// 1. 单消费者任务队列
public class TaskQueue {
private final UnicastProcessor<Task> taskProcessor = UnicastProcessor.create(1000);
private final Flowable<Task> taskStream;
private Disposable workerDisposable;
public TaskQueue() {
this.taskStream = taskProcessor
.onBackpressureBuffer(100)
.observeOn(Schedulers.io(), false, 16);
// 启动工作线程
this.workerDisposable = taskStream.subscribe(this::processTask);
}
public void submitTask(Task task) {
taskProcessor.onNext(task);
}
public void submitTasks(List<Task> tasks) {
tasks.forEach(taskProcessor::onNext);
}
public void shutdown() {
taskProcessor.onComplete();
if (workerDisposable != null && !workerDisposable.isDisposed()) {
workerDisposable.dispose();
}
}
public boolean isActive() {
return workerDisposable != null && !workerDisposable.isDisposed();
}
private void processTask(Task task) {
try {
task.execute();
} catch (Exception e) {
System.err.println("Task failed: " + e.getMessage());
}
}
}
// 2. 串行写入器
public class SerialWriter {
private final UnicastProcessor<byte[]> writeProcessor = UnicastProcessor.create(100);
private final OutputStream outputStream;
private Disposable writeDisposable;
public SerialWriter(OutputStream outputStream) {
this.outputStream = outputStream;
this.writeDisposable = writeProcessor
.onBackpressureBuffer(50)
.observeOn(Schedulers.io())
.subscribe(
data -> {
synchronized (outputStream) {
outputStream.write(data);
outputStream.flush();
}
},
error -> {
try {
outputStream.close();
} catch (IOException e) {
error.addSuppressed(e);
}
},
() -> {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
);
}
public void write(byte[] data) {
writeProcessor.onNext(data);
}
public void close() {
writeProcessor.onComplete();
if (writeDisposable != null && !writeDisposable.isDisposed()) {
writeDisposable.dispose();
}
}
public boolean isClosed() {
return writeProcessor.hasComplete() || writeProcessor.hasThrowable();
}
}
// 3. 命令处理器
public class CommandProcessor {
private final UnicastProcessor<Command> commandProcessor = UnicastProcessor.create(100);
private final Map<Class<? extends Command>, CommandHandler> handlers = new ConcurrentHashMap<>();
private Disposable processingDisposable;
public CommandProcessor() {
this.processingDisposable = commandProcessor
.onBackpressureBuffer(50)
.observeOn(Schedulers.io())
.subscribe(this::processCommand);
}
public void registerHandler(Class<? extends Command> commandType, CommandHandler handler) {
handlers.put(commandType, handler);
}
public void execute(Command command) {
commandProcessor.onNext(command);
}
public void shutdown() {
commandProcessor.onComplete();
if (processingDisposable != null && !processingDisposable.isDisposed()) {
processingDisposable.dispose();
}
}
private void processCommand(Command command) {
CommandHandler handler = handlers.get(command.getClass());
if (handler != null) {
try {
handler.handle(command);
} catch (Exception e) {
System.err.println("Command execution failed: " + e.getMessage());
}
} else {
System.err.println("No handler for command: " + command.getClass());
}
}
}