RxJava——Subject详解

Subject详解

一、概述

1.1、核心概念

Subject是RxJava中的特殊类型,它既是Observer(可以订阅其他Observable),又是Observable(可以被其他Observer订阅)。它作为事件总线或中继器使用。

继承关系:

java 复制代码
// Subject 继承关系
public abstract class Subject<T> extends Observable<T> implements Observer<T> {
    // 核心方法
    public abstract boolean hasObservers();
    public final boolean hasComplete();
    public final boolean hasThrowable();
    public final Throwable getThrowable();
    public final boolean hasComplete();
}

// 支持背压的Flowable版本
public abstract class FlowableProcessor<T> extends Flowable<T> implements FlowableSubscriber<T>, Processor<T, T> {
    public abstract boolean hasSubscribers();
}

1.2、Subject类型

类型 特性
PublishSubject 实时发布
BehaviorSubject 保留最新值
ReplaySubject 重放所有数据
AsyncSubject 只发射最后一个值
UnicastSubject 单播Subject
FlowableProcessor 支持背压的Flowable版本

二、AsyncSubject(只发射最后一个值)

2.1、核心特性

  • Observer会接收AsyncSubject的onComplete(之前的最后一个数据
  • 如果源Observable没有发射任何值就完成,AsyncSubject也不会发射任何值
  • 如果源Observable发生错误,AsyncSubject会传递这个错误
java 复制代码
@Test
public void testAsyncSubject() {
    //基本用法
    AsyncSubject<String> subject = AsyncSubject.create();

    //订阅者1
    subject.subscribe(
            data -> System.out.println("Subscriber 1:" + data),
            error -> System.out.println("Error:" + error),
            () -> System.out.println("Completed")
    );

    subject.onNext("Ignore 1");
    subject.onNext("Ignore 2");
    subject.onNext("Last Value");//只有这个值会被发射
    subject.onComplete();

    //订阅者2(也能收到最后的值)
    subject.subscribe(data -> System.out.println("Subscriber 2:" + data));
}

Subscriber 1:Last Value
Completed
Subscriber 2:Last Value

2.2、使用场景

java 复制代码
// 1. 异步计算结果
public class AsyncCalculator {
    private final AsyncSubject<Double> resultSubject = AsyncSubject.create();
    
    public void calculateAsync(List<Double> numbers) {
        Completable.fromAction(() -> {
            double sum = 0;
            for (Double num : numbers) {
                sum += num;
                // 中间结果被忽略
                resultSubject.onNext(sum);
            }
            resultSubject.onComplete();
        }).subscribeOn(Schedulers.computation()).subscribe();
    }
    
    public Observable<Double> getResult() {
        return resultSubject;
    }
}

// 2. 网络请求最终结果
public class ApiClient {
    private final AsyncSubject<Response> responseSubject = AsyncSubject.create();
    
    public void executeRequest(Request request) {
        apiService.call(request)
            .subscribe(
                response -> {
                    responseSubject.onNext(response);
                    responseSubject.onComplete();
                },
                error -> responseSubject.onError(error)
            );
    }
    
    public Observable<Response> getResponse() {
        return responseSubject;
    }
}

// 3. 数据库操作结果
public class DatabaseOperation<T> {
    private final AsyncSubject<T> operationSubject = AsyncSubject.create();
    
    public void executeOperation(Operation<T> operation) {
        database.execute(operation)
            .subscribe(
                result -> {
                    operationSubject.onNext(result);
                    operationSubject.onComplete();
                },
                error -> operationSubject.onError(error)
            );
    }
    
    public Observable<T> getResult() {
        return operationSubject;
    }
}

三、PublishSubject(实时发布)

3.1、核心特性

  • 只向订阅时已发射的数据之后的订阅者发射数据
  • 不缓存任何数据
  • 订阅者只能收到订阅之后发射的数据
java 复制代码
@Test
public void testPublishSubject() {
    //基本用法
    PublishSubject<String> subject = PublishSubject.create();

    //订阅者1
    subject.subscribe(
            data -> System.out.println("Subscriber 1:" + data),
            error -> System.out.println("Subscriber 1 Error:" + error),
            () -> System.out.println("Subscriber 1 Completed")
    );

    //发射数据
    subject.onNext("Data 1");
    subject.onNext("Data 2");

    //订阅者2(收不到之前的数据)
    subject.subscribe(
            data -> System.out.println("Subscriber 2:" + data),
            error -> System.out.println("Subscriber 2 Error:" + error),
            () -> System.out.println("Subscriber 2 Completed")
    );

    subject.onNext("Data 3");
    subject.onComplete();
}


Subscriber 1:Data 1
Subscriber 1:Data 2
Subscriber 1:Data 3
Subscriber 2:Data 3
Subscriber 1 Completed
Subscriber 2 Completed

3.2、使用场景

java 复制代码
// 1. 事件总线
public class EventBus {
    private static final PublishSubject<Event> bus = PublishSubject.create();
    
    public static void post(Event event) {
        bus.onNext(event);
    }
    
    public static Observable<Event> observe() {
        return bus;
    }
}

// 2. 实时数据更新
public class RealTimeDataManager {
    private final PublishSubject<StockPrice> priceSubject = PublishSubject.create();
    
    public void updatePrice(String symbol, double price) {
        priceSubject.onNext(new StockPrice(symbol, price));
    }
    
    public Observable<StockPrice> getPriceStream() {
        return priceSubject.filter(price -> price != null);
    }
}

// 3. 用户交互事件
public class UserInteractionHandler {
    private final PublishSubject<ClickEvent> clickSubject = PublishSubject.create();
    
    public void onButtonClicked(View view) {
        clickSubject.onNext(new ClickEvent(view.getId(), System.currentTimeMillis()));
    }
    
    public Observable<ClickEvent> getClicks() {
        return clickSubject.debounce(300, TimeUnit.MILLISECONDS);
    }
}

四、BehaviorSubject(保留最新值)

4.1、核心特性

  • 向订阅者发射最近的一个值和之后的所有值
  • 需要初始值(默认值)
  • 新订阅者立即收到最近的值
java 复制代码
@Test
public void testBehaviorSubject() {
    //基本用法
    BehaviorSubject<String> subject = BehaviorSubject.createDefault("Initial");

    //订阅者1
    subject.subscribe(data -> System.out.println("Subscriber 1:" + data));

    subject.onNext("Update 1");
    subject.onNext("Update 2");

    //订阅者2(立即收到最近的值update 2)
    subject.subscribe(data -> System.out.println("Subscriber 2:" + data));

    subject.onNext("Update 3");
    subject.onComplete();
}


Subscriber 1:Initial
Subscriber 1:Update 1
Subscriber 1:Update 2
Subscriber 2:Update 2
Subscriber 1:Update 3
Subscriber 2:Update 3

4.2、使用场景

java 复制代码
// 1. 状态管理
public class AppStateManager {
    private final BehaviorSubject<AppState> stateSubject = 
        BehaviorSubject.createDefault(AppState.IDLE);
    
    public void setState(AppState newState) {
        stateSubject.onNext(newState);
    }
    
    public Observable<AppState> getStateObservable() {
        return stateSubject.distinctUntilChanged();
    }
    
    public AppState getCurrentState() {
        return stateSubject.getValue();  // 获取当前值
    }
}

// 2. 数据缓存
public class CacheManager<T> {
    private final BehaviorSubject<Optional<T>> cacheSubject = 
        BehaviorSubject.createDefault(Optional.empty());
    
    public void updateCache(T data) {
        cacheSubject.onNext(Optional.of(data));
    }
    
    public void clearCache() {
        cacheSubject.onNext(Optional.empty());
    }
    
    public Observable<Optional<T>> getCacheStream() {
        return cacheSubject;
    }
    
    public Optional<T> getCurrentCache() {
        return cacheSubject.getValue();
    }
}

// 3. 表单验证
public class FormValidator {
    private final BehaviorSubject<Boolean> validSubject = 
        BehaviorSubject.createDefault(false);
    
    public void validate(String input) {
        boolean isValid = input != null && !input.trim().isEmpty();
        validSubject.onNext(isValid);
    }
    
    public Observable<Boolean> getValidationStream() {
        return validSubject;
    }
    
    public boolean isValid() {
        return Boolean.TRUE.equals(validSubject.getValue());
    }
}

五、ReplaySubject(重放所有数据)

5.1、核心特性

  • 向所有订阅者发射所有已发射的数据
  • 可配置缓冲区大小和时间窗口
  • 新订阅者立即收到所有历史数据
java 复制代码
@Test
public void testReplaySubject() throws InterruptedException {
    //1. 无限缓存
    ReplaySubject<String> unlimited = ReplaySubject.create();
    unlimited.onNext("Data 1");
    unlimited.onNext("Data 2");
    unlimited.subscribe(data -> System.out.println("Subscriber:" + data));
    //输出:Data 1, Data 2

    //2.限制缓存大小
    ReplaySubject<Integer> sizeLimited = ReplaySubject.createWithSize(2);
    sizeLimited.onNext(1);
    sizeLimited.onNext(2);
    sizeLimited.onNext(3);//超出限制,1被丢弃
    sizeLimited.subscribe(System.out::println);
    //输出:2,3

    //限制时间窗口
    ReplaySubject<String> timeLimited = ReplaySubject.createWithTime(1, TimeUnit.SECONDS, Schedulers.computation());
    timeLimited.onNext("Data 1");
    Thread.sleep(500);
    timeLimited.onNext("Data 2");
    Thread.sleep(600);//Data1过期
    timeLimited.subscribe(System.out::println);
    //输出:Data 2

    //4. 限制大小和时间
    ReplaySubject<String> bounded = ReplaySubject.createWithTimeAndSize(
            1, TimeUnit.SECONDS,//时间窗口
            Schedulers.computation(),
            100
    );


    Thread.sleep(6000L);
}


Subscriber:Data 1
Subscriber:Data 2
2
3
Data 2

5.2、使用场景

java 复制代码
// 1. 日志记录器
public class Logger {
    private final ReplaySubject<LogEntry> logSubject = 
        ReplaySubject.createWithSize(1000);  // 保留最近1000条日志
    
    public void log(Level level, String message) {
        logSubject.onNext(new LogEntry(level, message, System.currentTimeMillis()));
    }
    
    public Observable<LogEntry> getLogStream() {
        return logSubject;
    }
    
    public List<LogEntry> getRecentLogs(int count) {
        List<LogEntry> logs = new ArrayList<>();
        logSubject.takeLast(count).subscribe(logs::add);
        return logs;
    }
}

// 2. 聊天消息历史
public class ChatRoom {
    private final ReplaySubject<Message> messageSubject = 
        ReplaySubject.createWithTime(1, TimeUnit.HOURS, Schedulers.io());
    
    public void sendMessage(User sender, String content) {
        messageSubject.onNext(new Message(sender, content, System.currentTimeMillis()));
    }
    
    public Observable<Message> getMessageStream() {
        return messageSubject;
    }
    
    public void replayHistoryFor(User user) {
        // 新用户加入时重放历史消息
        messageSubject
            .takeUntil(msg -> msg.getTimestamp() > System.currentTimeMillis() - 300000)  // 最近5分钟
            .subscribe(msg -> sendToUser(user, msg));
    }
}

// 3. 传感器数据记录
public class SensorDataRecorder {
    private final ReplaySubject<SensorData> dataSubject = 
        ReplaySubject.createWithTimeAndSize(
            10, TimeUnit.MINUTES,  // 10分钟窗口
            10000,                 // 最多10000个数据点
            Schedulers.computation()
        );
    
    public void recordData(SensorData data) {
        dataSubject.onNext(data);
    }
    
    public Observable<SensorData> getDataStream() {
        return dataSubject;
    }
    
    public Observable<SensorData> getRecentData(long duration, TimeUnit unit) {
        long cutoff = System.currentTimeMillis() - unit.toMillis(duration);
        return dataSubject.filter(data -> data.getTimestamp() >= cutoff);
    }
}

六、UnicastSubject(单播Subject支持背压)

6.1、核心特性

  • 只允许一个订阅者
  • 支持背压
  • 如果没有订阅者,会缓存数据直到有订阅者订阅
java 复制代码
@Test
public void testUnicastSubject() {
    //基本用法
    UnicastSubject<String> subject = UnicastSubject.create();

    //发射数据(还咩有订阅者,数据被缓存)
    subject.onNext("Cached 1");
    subject.onNext("Cached 2");

    //订阅者(立即受到缓存的数据)
    subject.subscribe(
            data -> System.out.println("Received:" + data),
            error -> System.out.println("Error:" + error),
            () -> System.out.println("Completed")
    );

    subject.onNext("Live 1");
    subject.onComplete();

    //尝试第二个订阅者会抛异常
    try {
        subject.subscribe(data -> System.out.println("Second:" + data));
    } catch (IllegalStateException e) {
        System.out.println("只能有一个订阅者:" + e.getMessage());
    }
}

Received:Cached 1
Received:Cached 2
Received:Live 1
Completed

6.2、使用场景

java 复制代码
// 1. 单消费者队列
public class SingleConsumerQueue<T> {
    private final UnicastSubject<T> queueSubject = UnicastSubject.create();
    
    public void enqueue(T item) {
        queueSubject.onNext(item);
    }
    
    public void complete() {
        queueSubject.onComplete();
    }
    
    public Observable<T> getConsumerStream() {
        return queueSubject
            .onBackpressureBuffer()  // 支持背压
            .observeOn(Schedulers.io());
    }
}

// 2. 任务处理器
public class TaskProcessor {
    private final UnicastSubject<Task> taskSubject = UnicastSubject.create();
    private Disposable processorDisposable;
    
    public TaskProcessor() {
        // 启动处理线程
        processorDisposable = taskSubject
            .observeOn(Schedulers.io())
            .subscribe(this::processTask);
    }
    
    public void submitTask(Task task) {
        taskSubject.onNext(task);
    }
    
    public void shutdown() {
        taskSubject.onComplete();
        if (processorDisposable != null && !processorDisposable.isDisposed()) {
            processorDisposable.dispose();
        }
    }
    
    private void processTask(Task task) {
        // 处理任务
    }
}

// 3. 数据序列化写入
public class SerialWriter {
    private final UnicastSubject<byte[]> writeSubject = UnicastSubject.create();
    private final OutputStream outputStream;
    
    public SerialWriter(OutputStream outputStream) {
        this.outputStream = outputStream;
        
        // 单个写入线程
        writeSubject
            .observeOn(Schedulers.io())
            .subscribe(
                data -> outputStream.write(data),
                error -> System.err.println("Write error: " + error),
                () -> {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            );
    }
    
    public void write(byte[] data) {
        writeSubject.onNext(data);
    }
    
    public void close() {
        writeSubject.onComplete();
    }
}

七、Subject高级用法

7.1、Subject的序列化

java 复制代码
// Subject默认不是线程安全的
public class SerializedSubjectExample {
    
    // 1. 使用toSerialized()方法
    public static PublishSubject<String> createSerializedSubject() {
        PublishSubject<String> subject = PublishSubject.create();
        return subject.toSerialized();  // 转换为线程安全的Subject
    }
    
    // 2. 直接创建序列化Subject
    public static BehaviorSubject<String> createSerializedBehaviorSubject() {
        return BehaviorSubject.<String>create().toSerialized();
    }
    
    // 使用示例
    public static void concurrentAccessExample() {
        PublishSubject<String> subject = PublishSubject.create().toSerialized();
        
        // 多线程并发访问
        ExecutorService executor = Executors.newFixedThreadPool(5);
        
        // 多个线程同时发射数据
        for (int i = 0; i < 10; i++) {
            final int index = i;
            executor.submit(() -> {
                subject.onNext("Data from thread " + Thread.currentThread().getId() + "-" + index);
            });
        }
        
        // 订阅
        subject.subscribe(data -> 
            System.out.println("Received: " + data + " on thread " + Thread.currentThread().getId())
        );
        
        executor.shutdown();
    }
}

// 序列化Subject的原理
public class CustomSerializedSubject<T> extends Subject<T> {
    private final Subject<T> actual;
    private volatile boolean emitting;
    private final List<T> queue = new ArrayList<>();
    
    public CustomSerializedSubject(Subject<T> actual) {
        this.actual = actual;
    }
    
    @Override
    public void onNext(T t) {
        synchronized (this) {
            if (emitting) {
                queue.add(t);
                return;
            }
            emitting = true;
        }
        
        actual.onNext(t);
        
        // 清空队列
        drainLoop();
    }
    
    private void drainLoop() {
        List<T> localQueue;
        synchronized (this) {
            localQueue = new ArrayList<>(queue);
            queue.clear();
            if (localQueue.isEmpty()) {
                emitting = false;
                return;
            }
        }
        
        for (T item : localQueue) {
            actual.onNext(item);
        }
        
        drainLoop();
    }
    
    // 其他方法实现...
}

7.2、Subject组合模式

java 复制代码
public class SubjectComposition {
    
    // 1. 多层Subject
    public static class MultiLayerEventBus {
        private final PublishSubject<SystemEvent> systemBus = PublishSubject.create();
        private final PublishSubject<UserEvent> userBus = PublishSubject.create();
        private final PublishSubject<NetworkEvent> networkBus = PublishSubject.create();
        
        // 合并所有事件
        private final Observable<Event> allEvents = Observable.merge(
            systemBus.map(e -> (Event)e),
            userBus.map(e -> (Event)e),
            networkBus.map(e -> (Event)e)
        );
        
        public void postSystemEvent(SystemEvent event) {
            systemBus.onNext(event);
        }
        
        public void postUserEvent(UserEvent event) {
            userBus.onNext(event);
        }
        
        public Observable<Event> getAllEvents() {
            return allEvents;
        }
        
        public Observable<SystemEvent> getSystemEvents() {
            return systemBus;
        }
    }
    
    // 2. Subject链
    public static class ProcessingPipeline {
        private final PublishSubject<RawData> input = PublishSubject.create();
        private final BehaviorSubject<ProcessedData> output = BehaviorSubject.create();
        
        public ProcessingPipeline() {
            // 构建处理链
            input
                .observeOn(Schedulers.computation())
                .map(this::validate)
                .filter(Objects::nonNull)
                .map(this::transform)
                .map(this::enrich)
                .subscribe(
                    output::onNext,
                    output::onError
                );
        }
        
        public void feedData(RawData data) {
            input.onNext(data);
        }
        
        public Observable<ProcessedData> getOutput() {
            return output;
        }
        
        private RawData validate(RawData data) {
            return data.isValid() ? data : null;
        }
        
        private ProcessedData transform(RawData data) {
            return new ProcessedData(data);
        }
        
        private ProcessedData enrich(ProcessedData data) {
            return data.enrich();
        }
    }
    
    // 3. Subject作为桥接
    public static class AdapterBridge {
        private final PublishSubject<LegacyEvent> legacyInput = PublishSubject.create();
        private final PublishSubject<ModernEvent> modernOutput = PublishSubject.create();
        
        public AdapterBridge() {
            // 将旧系统事件转换为新系统事件
            legacyInput
                .map(this::adaptEvent)
                .subscribe(modernOutput::onNext);
        }
        
        public void receiveLegacyEvent(LegacyEvent event) {
            legacyInput.onNext(event);
        }
        
        public Observable<ModernEvent> getModernEvents() {
            return modernOutput;
        }
        
        private ModernEvent adaptEvent(LegacyEvent legacy) {
            return new ModernEvent(
                legacy.getId(),
                legacy.getTimestamp(),
                legacy.getPayload()
            );
        }
    }
}

7.3、Subject的背压处理

java 复制代码
public class BackpressureWithSubject {
    
    // 1. 使用FlowableProcessor(支持背压的Subject)
    public static class BackpressureEventBus {
        private final PublishProcessor<Event> processor = PublishProcessor.create();
        
        public void postEvent(Event event) {
            processor.onNext(event);
        }
        
        public Flowable<Event> getEventStream() {
            return processor
                .onBackpressureBuffer(1000)  // 缓冲区大小
                .onBackpressureDrop(dropped -> 
                    System.out.println("Dropped event: " + dropped)
                );
        }
    }
    
    // 2. 使用SerializedSubject处理背压
    public static class SerializedBackpressureSubject<T> {
        private final PublishSubject<T> subject = PublishSubject.create();
        private final SerializedSubject<T> serialized = subject.toSerialized();
        private final Flowable<T> backpressureFlowable;
        
        public SerializedBackpressureSubject(int bufferSize) {
            this.backpressureFlowable = serialized
                .toFlowable(BackpressureStrategy.BUFFER)
                .onBackpressureBuffer(
                    bufferSize,
                    () -> System.out.println("Buffer overflow"),
                    BackpressureOverflowStrategy.DROP_OLDEST
                );
        }
        
        public void emit(T item) {
            serialized.onNext(item);
        }
        
        public Flowable<T> asFlowable() {
            return backpressureFlowable;
        }
    }
    
    // 3. 速率限制
    public static class RateLimitedSubject<T> {
        private final PublishSubject<T> subject = PublishSubject.create();
        private final Observable<T> rateLimited;
        private long lastEmitTime = 0;
        
        public RateLimitedSubject(long minInterval, TimeUnit unit) {
            this.rateLimited = subject
                .filter(item -> {
                    long now = System.currentTimeMillis();
                    if (now - lastEmitTime >= unit.toMillis(minInterval)) {
                        lastEmitTime = now;
                        return true;
                    }
                    return false;
                })
                .share();  // 共享Observable
        }
        
        public void tryEmit(T item) {
            subject.onNext(item);
        }
        
        public Observable<T> getStream() {
            return rateLimited;
        }
    }
}

八、Subject内存管理

8.1、防止内存泄露

java 复制代码
public class SafeSubjectUsage {
    
    // 1. 使用弱引用订阅者
    public static class WeakSubject<T> {
        private final PublishSubject<T> subject = PublishSubject.create();
        private final Map<Observer<? super T>, WeakReference<Observer<? super T>>> weakObservers = 
            new ConcurrentHashMap<>();
        
        public Disposable subscribeWeak(Observer<? super T> observer) {
            WeakReference<Observer<? super T>> weakRef = new WeakReference<>(observer);
            weakObservers.put(observer, weakRef);
            
            Disposable disposable = subject.subscribe(
                item -> {
                    Observer<? super T> obs = weakRef.get();
                    if (obs != null) {
                        obs.onNext(item);
                    } else {
                        // 观察者已被GC,清理弱引用
                        weakObservers.remove(observer);
                    }
                },
                error -> {
                    Observer<? super T> obs = weakRef.get();
                    if (obs != null) {
                        obs.onError(error);
                    }
                    weakObservers.remove(observer);
                },
                () -> {
                    Observer<? super T> obs = weakRef.get();
                    if (obs != null) {
                        obs.onComplete();
                    }
                    weakObservers.remove(observer);
                }
            );
            
            return new Disposable() {
                @Override
                public void dispose() {
                    disposable.dispose();
                    weakObservers.remove(observer);
                }
                
                @Override
                public boolean isDisposed() {
                    return disposable.isDisposed();
                }
            };
        }
        
        public void onNext(T item) {
            subject.onNext(item);
        }
    }
    
    // 2. 自动清理的Subject
    public static class AutoCleanupSubject<T> extends Subject<T> {
        private final PublishSubject<T> delegate = PublishSubject.create();
        private final CompositeDisposable disposables = new CompositeDisposable();
        private final long timeout;
        private final TimeUnit timeUnit;
        
        public AutoCleanupSubject(long timeout, TimeUnit timeUnit) {
            this.timeout = timeout;
            this.timeUnit = timeUnit;
        }
        
        @Override
        protected void subscribeActual(Observer<? super T> observer) {
            Disposable disposable = delegate.subscribe(observer);
            disposables.add(disposable);
            
            // 设置超时自动清理
            Disposable timeoutDisposable = Completable.timer(timeout, timeUnit)
                .subscribe(() -> {
                    if (!disposable.isDisposed()) {
                        disposable.dispose();
                        disposables.remove(disposable);
                    }
                });
            
            disposables.add(timeoutDisposable);
        }
        
        @Override
        public void onNext(T t) {
            delegate.onNext(t);
        }
        
        @Override
        public void onError(Throwable e) {
            delegate.onError(e);
        }
        
        @Override
        public void onComplete() {
            delegate.onComplete();
        }
        
        @Override
        public boolean hasObservers() {
            return delegate.hasObservers();
        }
        
        public void cleanup() {
            disposables.clear();
        }
    }
    
    // 3. 使用CompositeDisposable管理订阅
    public static class ManagedSubject<T> {
        private final Subject<T> subject;
        private final CompositeDisposable compositeDisposable = new CompositeDisposable();
        
        public ManagedSubject(Subject<T> subject) {
            this.subject = subject.toSerialized();  // 线程安全
        }
        
        public Disposable subscribeManaged(Observer<? super T> observer) {
            Disposable disposable = subject.subscribe(observer);
            compositeDisposable.add(disposable);
            return disposable;
        }
        
        public void emit(T item) {
            subject.onNext(item);
        }
        
        public void disposeAll() {
            compositeDisposable.clear();
        }
        
        public boolean isDisposed() {
            return compositeDisposable.isDisposed();
        }
    }
}

8.2、Subject的引用计数

java 复制代码
public class ReferenceCountedSubject<T> extends Subject<T> {
    private final PublishSubject<T> delegate = PublishSubject.create();
    private int refCount = 0;
    private final Object lock = new Object();
    
    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        synchronized (lock) {
            refCount++;
        }
        
        Disposable disposable = delegate.subscribe(observer);
        
        return new Disposable() {
            @Override
            public void dispose() {
                disposable.dispose();
                synchronized (lock) {
                    refCount--;
                    if (refCount == 0) {
                        cleanup();
                    }
                }
            }
            
            @Override
            public boolean isDisposed() {
                return disposable.isDisposed();
            }
        };
    }
    
    @Override
    public void onNext(T t) {
        delegate.onNext(t);
    }
    
    @Override
    public void onError(Throwable e) {
        delegate.onError(e);
    }
    
    @Override
    public void onComplete() {
        delegate.onComplete();
    }
    
    @Override
    public boolean hasObservers() {
        return delegate.hasObservers();
    }
    
    public int getRefCount() {
        synchronized (lock) {
            return refCount;
        }
    }
    
    private void cleanup() {
        // 清理资源
        System.out.println("No more observers, cleaning up...");
    }
}

九、Subject性能优化

9.1、高效事件分发

java 复制代码
public class EfficientSubject<T> {
    
    // 1. 使用数组存储观察者
    public static class FastPublishSubject<T> extends Subject<T> {
        private final List<Observer<? super T>> observers = new CopyOnWriteArrayList<>();
        
        @Override
        protected void subscribeActual(Observer<? super T> observer) {
            observers.add(observer);
            observer.onSubscribe(new Disposable() {
                private volatile boolean disposed;
                
                @Override
                public void dispose() {
                    disposed = true;
                    observers.remove(observer);
                }
                
                @Override
                public boolean isDisposed() {
                    return disposed;
                }
            });
        }
        
        @Override
        public void onNext(T t) {
            for (Observer<? super T> observer : observers) {
                if (!((Disposable)observer).isDisposed()) {
                    observer.onNext(t);
                }
            }
        }
        
        @Override
        public void onError(Throwable e) {
            for (Observer<? super T> observer : observers) {
                observer.onError(e);
            }
        }
        
        @Override
        public void onComplete() {
            for (Observer<? super T> observer : observers) {
                observer.onComplete();
            }
        }
        
        @Override
        public boolean hasObservers() {
            return !observers.isEmpty();
        }
    }
    
    // 2. 批处理事件
    public static class BatchedSubject<T> extends Subject<T> {
        private final PublishSubject<T> delegate = PublishSubject.create();
        private final List<T> batchBuffer = new ArrayList<>();
        private final int batchSize;
        private final Scheduler scheduler;
        
        public BatchedSubject(int batchSize, Scheduler scheduler) {
            this.batchSize = batchSize;
            this.scheduler = scheduler;
        }
        
        @Override
        protected void subscribeActual(Observer<? super T> observer) {
            delegate.subscribe(observer);
        }
        
        @Override
        public void onNext(T t) {
            synchronized (batchBuffer) {
                batchBuffer.add(t);
                if (batchBuffer.size() >= batchSize) {
                    emitBatch();
                }
            }
        }
        
        @Override
        public void onError(Throwable e) {
            emitBatch();  // 发射剩余数据
            delegate.onError(e);
        }
        
        @Override
        public void onComplete() {
            emitBatch();  // 发射剩余数据
            delegate.onComplete();
        }
        
        @Override
        public boolean hasObservers() {
            return delegate.hasObservers();
        }
        
        private void emitBatch() {
            synchronized (batchBuffer) {
                if (!batchBuffer.isEmpty()) {
                    List<T> batch = new ArrayList<>(batchBuffer);
                    batchBuffer.clear();
                    scheduler.scheduleDirect(() -> {
                        for (T item : batch) {
                            delegate.onNext(item);
                        }
                    });
                }
            }
        }
    }
}

9.2、零拷贝数据传输

java 复制代码
public class ZeroCopySubject<T> {
    
    public static class SharedBufferSubject<T> extends Subject<T> {
        private final PublishSubject<BufferReference<T>> delegate = PublishSubject.create();
        private final ThreadLocal<BufferReference<T>> threadLocalBuffer = 
            ThreadLocal.withInitial(BufferReference::new);
        
        @Override
        protected void subscribeActual(Observer<? super T> observer) {
            delegate.subscribe(
                bufferRef -> {
                    T data = bufferRef.getAndClear();
                    if (data != null) {
                        observer.onNext(data);
                    }
                },
                observer::onError,
                observer::onComplete
            );
        }
        
        @Override
        public void onNext(T t) {
            BufferReference<T> bufferRef = threadLocalBuffer.get();
            bufferRef.set(t);
            delegate.onNext(bufferRef);
        }
        
        @Override
        public void onError(Throwable e) {
            delegate.onError(e);
        }
        
        @Override
        public void onComplete() {
            delegate.onComplete();
        }
        
        @Override
        public boolean hasObservers() {
            return delegate.hasObservers();
        }
        
        static class BufferReference<T> {
            private T data;
            
            public void set(T data) {
                this.data = data;
            }
            
            public T getAndClear() {
                T temp = data;
                data = null;
                return temp;
            }
        }
    }
}

十、常见问题解决方案

10.1、内存泄露问题

java 复制代码
public class SubjectMemoryLeakSolutions {
    
    // 问题:长期持有Observer引用
    public static class LeakingSubject {
        private final PublishSubject<Event> subject = PublishSubject.create();
        private final List<Observer<Event>> observers = new ArrayList<>();
        
        public void addObserver(Observer<Event> observer) {
            observers.add(observer);
            subject.subscribe(observer);  // ❌ 订阅后持有observer引用
        }
        
        public void removeObserver(Observer<Event> observer) {
            observers.remove(observer);
            // ❌ 无法从subject取消订阅
        }
    }
    
    // 解决方案1:使用CompositeDisposable
    public static class SafeSubject1 {
        private final PublishSubject<Event> subject = PublishSubject.create();
        private final CompositeDisposable disposables = new CompositeDisposable();
        
        public void addObserver(Observer<Event> observer) {
            Disposable disposable = subject.subscribe(observer);
            disposables.add(disposable);
        }
        
        public void removeAllObservers() {
            disposables.clear();
        }
    }
    
    // 解决方案2:使用WeakReference
    public static class SafeSubject2 {
        private final PublishSubject<Event> subject = PublishSubject.create();
        private final Map<Observer<Event>, Disposable> observerMap = 
            new WeakHashMap<>();
        
        public void addObserver(Observer<Event> observer) {
            Disposable disposable = subject.subscribe(observer);
            observerMap.put(observer, disposable);
        }
        
        public void removeObserver(Observer<Event> observer) {
            Disposable disposable = observerMap.remove(observer);
            if (disposable != null) {
                disposable.dispose();
            }
        }
    }
}

10.2、线程安全问题

java 复制代码
public class SubjectThreadSafety {
    
    // 问题:非线程安全的Subject
    public static class UnsafeSubjectUsage {
        private final PublishSubject<String> subject = PublishSubject.create();  // ❌ 非线程安全
        
        public void emitFromMultipleThreads() {
            ExecutorService executor = Executors.newFixedThreadPool(5);
            for (int i = 0; i < 10; i++) {
                executor.submit(() -> {
                    subject.onNext("Data from " + Thread.currentThread().getId());
                });
            }
            // 可能发生并发修改异常
        }
    }
    
    // 解决方案:使用序列化Subject
    public static class ThreadSafeSubject {
        private final PublishSubject<String> subject = 
            PublishSubject.<String>create().toSerialized();  // ✅ 线程安全
        
        public void emitFromMultipleThreads() {
            ExecutorService executor = Executors.newFixedThreadPool(5);
            for (int i = 0; i < 10; i++) {
                executor.submit(() -> {
                    subject.onNext("Data from " + Thread.currentThread().getId());
                });
            }
        }
    }
}

10.3、背压问题

java 复制代码
public class SubjectBackpressure {
    
    // 问题:快速生产者,慢速消费者
    public static class BackpressureProblem {
        private final PublishSubject<Integer> subject = PublishSubject.create();
        
        public void causeBackpressure() {
            // 快速生产
            Observable.range(1, 1000000)
                .subscribe(subject::onNext);
            
            // 慢速消费
            subject
                .observeOn(Schedulers.io())
                .subscribe(i -> {
                    Thread.sleep(10);  // 慢速处理
                    System.out.println(i);
                });
            // ❌ 可能OOM
        }
    }
    
    // 解决方案1:使用FlowableProcessor
    public static class BackpressureSolution1 {
        private final PublishProcessor<Integer> processor = PublishProcessor.create();
        
        public void handleBackpressure() {
            Observable.range(1, 1000000)
                .subscribe(
                    processor::onNext,
                    processor::onError,
                    processor::onComplete
                );
            
            processor
                .onBackpressureBuffer(1000)  // 缓冲区
                .observeOn(Schedulers.io())
                .subscribe(i -> {
                    Thread.sleep(10);
                    System.out.println(i);
                });
        }
    }
    
    // 解决方案2:使用Subject + 背压策略
    public static class BackpressureSolution2 {
        private final PublishSubject<Integer> subject = PublishSubject.create();
        
        public void handleBackpressure() {
            Observable.range(1, 1000000)
                .subscribe(subject::onNext);
            
            subject
                .toFlowable(BackpressureStrategy.DROP)  // 背压策略
                .observeOn(Schedulers.io())
                .subscribe(i -> {
                    Thread.sleep(10);
                    System.out.println(i);
                });
        }
    }
}

十一、最佳实践

11.1、选择正确的Subject类型

java 复制代码
public class SubjectSelectionGuide {
    
    public static Subject<?> selectSubject(UseCase useCase) {
        switch (useCase) {
            case EVENT_BUS:
                // 事件总线:只需要实时事件
                return PublishSubject.create().toSerialized();
                
            case STATE_MANAGEMENT:
                // 状态管理:需要当前状态
                return BehaviorSubject.create().toSerialized();
                
            case DATA_REPLAY:
                // 数据重放:需要历史数据
                return ReplaySubject.createWithSize(1000).toSerialized();
                
            case ASYNC_RESULT:
                // 异步结果:只需要最终结果
                return AsyncSubject.create();
                
            case SINGLE_CONSUMER:
                // 单消费者:确保只有一个订阅者
                return UnicastSubject.create();
                
            case BACKPRESSURE_NEEDED:
                // 需要背压:使用FlowableProcessor
                return PublishProcessor.create();
                
            default:
                throw new IllegalArgumentException("Unknown use case");
        }
    }
    
    enum UseCase {
        EVENT_BUS,
        STATE_MANAGEMENT,
        DATA_REPLAY,
        ASYNC_RESULT,
        SINGLE_CONSUMER,
        BACKPRESSURE_NEEDED
    }
}

11.2、Subject的封装模式

java 复制代码
public class SubjectWrapper<T> {
    private final Subject<T> subject;
    private final CompositeDisposable disposables = new CompositeDisposable();
    
    private SubjectWrapper(Subject<T> subject) {
        this.subject = subject.toSerialized();  // 自动序列化
    }
    
    public static <T> SubjectWrapper<T> publish() {
        return new SubjectWrapper<>(PublishSubject.create());
    }
    
    public static <T> SubjectWrapper<T> behavior(T defaultValue) {
        return new SubjectWrapper<>(BehaviorSubject.createDefault(defaultValue));
    }
    
    public static <T> SubjectWrapper<T> replay(int bufferSize) {
        return new SubjectWrapper<>(ReplaySubject.createWithSize(bufferSize));
    }
    
    public Disposable subscribe(Observer<? super T> observer) {
        Disposable disposable = subject.subscribe(observer);
        disposables.add(disposable);
        return disposable;
    }
    
    public void emit(T value) {
        subject.onNext(value);
    }
    
    public void complete() {
        subject.onComplete();
    }
    
    public void error(Throwable throwable) {
        subject.onError(throwable);
    }
    
    public Observable<T> asObservable() {
        return subject.hide();  // 隐藏Subject特性
    }
    
    public void disposeAll() {
        disposables.clear();
    }
    
    public boolean hasObservers() {
        return subject.hasObservers();
    }
}
相关推荐
Kapaseker4 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴4 小时前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭14 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab15 小时前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
这个实现不了21 小时前
echarts实例:可堆叠的立体柱形图+特殊symbol的折线图
echarts
这个实现不了21 小时前
echarts实例:进度条加描述
echarts
BoomHe21 小时前
Now in Android 架构模式全面分析
android·android jetpack
这个实现不了21 小时前
echarts实例:最高最低标识-并列立体柱形图
echarts
这个实现不了21 小时前
echarts实例:双轴水平条形图(菱形和三角形的symbol)
echarts
这个实现不了21 小时前
echarts实例:雷达图做出时钟效果
echarts