选择水槽/处理器的反应器

时间:2018-01-12 15:41:44

标签: java multithreading project-reactor

我有以下用例:

在一个应用程序中,我正在使用X线程消耗一些消息,其中我有一个像这样定义的Consumer实现:

public interface Consumer {
     onMessage(Object message);
}

问题是Consumer不是每个线程不同的实例,而是单个实例,因为它是一个Spring bean,我们也希望每次调用onMessage都不会产生副作用。

但是,我想要构建的是一个重复的消息检测机制,它看起来像这样:

public static <T> Flux<OcurrenceCache<T>> getExceedingRates(Flux<T> values, int maxHits, int bufferSize, Duration bufferTimeout) {
        return values.bufferTimeout(bufferSize, bufferTimeout)
            .map(vals -> {
                OcurrenceCache<T> occurrenceCache = new OcurrenceCache<>(maxHits);
                for (T value : vals) {
                    occurrenceCache.incrementNrOccurrences(value);
                }
                return occurrenceCache;
            });
}

在基本上来自值的通量的情况下,我将返回一个事件缓存,其中遇到的元素超过了所需的最大命中数。

天真地,我可以实现这样的事情:

public class MyConsumer implements Consumer {
    private final EmitterProcessor<Object> emitterProcessor;

    public MyConsumer(Integer maxHits, Integer bufferSize, Long timeoutMillis){
       this.emitterProcessor = EmitterProcessor.create();
       this.emitterProcessor
                .bufferTimeout(bufferSize, Duration.ofMillis(timeoutMillis))
                .subscribe(integers -> {
                    getExceedingRates(Flux.fromIterable(integers), maxHits, bufferSize, Duration.ofMillis(timeoutMillis))
                            .subscribe(integerOcurrenceCache -> {
                                System.out.println(integerOcurrenceCache.getExceedingValues());
                        });
                });
    }

    @Override
    public void onMessage(Object message){
        emitterProcessor.onNext(message); 
    }
}

然而,这远非最佳,因为我知道来自特定线程的消息从不包含来自另一个线程的任何消息(它们是预先分组的,因为我们使用jms分组和kinesis sharding)。所以,在某种程度上,我想使用这样的处理器:

  • 使用调用onMessage的相同线程来隔离通量,使得来自它的值被隔离并且不会与从另一个线程放入的变量混淆。

1 个答案:

答案 0 :(得分:1)

您可以使用线程本地处理器:

private final ThreadLocal<EmitterProcessor<Object>> emitterProcessorHolder = ThreadLocal.withInitial(() -> {
  EmitterProcessor<Object> processor = ...
  return processor;
});
...
@Override
public void onMessage(Object message){
  emitterProcessorHolder.get().onNext(message); 
}