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();
    }
}
相关推荐
冬奇Lab8 小时前
Android系统启动流程深度解析:从Bootloader到Zygote的完整旅程
android·源码阅读
泓博10 小时前
Android中仿照View selector自定义Compose Button
android·vue.js·elementui
zhangphil11 小时前
Android性能分析中trace上到的postAndWait
android
十里-11 小时前
vue2的web项目打包成安卓apk包
android·前端
p***199411 小时前
MySQL——内置函数
android·数据库·mysql
兆子龙12 小时前
我成了🤡, 因为不想看广告,花了40美元自己写了个鸡肋挂机脚本
android·javascript
儿歌八万首13 小时前
Android 全局监听神器:registerActivityLifecycleCallbacks 解析
android·kotlin·activity
弹幕教练宇宙起源14 小时前
cmake文件介绍及用法
android·linux·c++
&岁月不待人&14 小时前
一个Android高级开发的2025总结 【个人总结无大话】
android
吴声子夜歌15 小时前
RxJava——FlowableProcessor详解
android·echarts·rxjava