Flux e Mono são usados como fontes de dados. Há muitas maneiras de gerar dados. Este artigo lista e descreve resumidamente os métodos comumente usados. Lugares insuficientes podem ir para o documento de origem para visualização.
Fonte de dados vazia ou fonte de dados especial
vazio
Com o método vazio, um fluxo de dados vazio pode ser criado.
Flux.empty();
Mono.empty();
erro
Com o método de erro, um fluxo de dados incorreto pode ser criado.
Flux.error(new RuntimeException("error"));
Mono.error(new RuntimeException("error"));
nunca
Com o método never, você pode criar um fluxo de dados que nunca emitirá nenhum sinal.
Flux.never();
Mono.never();
fonte de dados simples
apenas
Com o método just, você pode criar um fluxo de dados que contém elementos fixos.
Flux.just("foo", "bar", "foobar");
Mono.just("foo");
faixa
Com o método range, você pode criar um fluxo de dados que contém um intervalo especificado de números inteiros.
FLux<Integer> flux = Flux.range(1, 10);
fromArray
Por meio do método fromArray, você pode criar um fluxo de dados contendo os elementos do array.
Flux.fromArray(new Integer[]{
1, 2, 3});
fromIterable
Por meio do método fromIterable, você pode criar um fluxo de dados contendo elementos Iterable.
Flux.fromIterable(Arrays.asList("foo", "bar", "foobar"));
fromStream
Por meio do método fromStream, você pode criar um fluxo de dados que contém elementos Stream.
Flux.fromStream(Stream.of("foo", "bar", "foobar"));
do futuro
Por meio do método fromFuture, um fluxo de dados contendo elementos CompletableFuture pode ser criado.
Mono.fromFuture(CompletableFuture.completedFuture("foo"));
fromRunnable
Por meio do método fromRunnable, você pode criar um fluxo de dados contendo elementos Runnable.
Mono.fromRunnable(() -> System.out.println("foo"));
Intervalo gera tempo de intervalo para enviar dados
intervalo
Com o método interval, você pode criar um fluxo de dados que envia elementos em intervalos regulares.
Flux.interval(Duration.ofSeconds(1));
intervaloMilis
Com o método intervalMillis, você pode criar um fluxo de dados que envia elementos em intervalos regulares.
Flux.intervalMillis(1000);
Métodos avançados geram e criam
gerar
Por meio do método generate, você pode personalizar a geração de fluxos de dados. O método generate gera elementos de forma síncrona, um por vez. Isso significa que quando um elemento é consumido, o próximo elemento será produzido. O coletor é um SynchronousSink que fornece o método next() para gerar elementos.
generate tem vários métodos sobrecarregados.
Flux.generate(generator);
Flux.generate(stateSupplier,generator);
/**
* @param stateSupplier 一个无参函数,返回一个初始状态
* @param generator 一个BiFunction,接受状态和SynchronousSink,返回新的状态
* @param stateConsumer 一个Consumer,接受状态,用于清理资源
*/
Flux.generate(stateSupplier,generator,stateConsumer)
A demonstração específica é a seguinte:
Flux.generate(sink->{
sink.next("Hello");
sink.complete();
});
Flux.generate(()->0,(state,sink)->{
sink.next("3 x "+state+" = "+3*state);
if(state==10)sink.complete();
return state+1;
});
criar
Por meio do método create, você pode personalizar a geração de fluxos de dados. O método create é mais avançado do que o método generate.Ele pode gerar um elemento por vez de forma síncrona ou vários elementos por vez de forma assíncrona. Este método usa o FluxSink, que também fornece os métodos next, error e
complete. Ao contrário de generate, create não requer um valor de estado, por outro lado, pode disparar vários eventos no callback (mesmo em algum momento no futuro).
//create方法的接口
Flux.create(Consumer<? super FluxSink<T>>emitter)
/**
*
*/
Flux.create(Consumer<? super FluxSink<T>>emitter,FluxSink.OverflowStrategy overflowStrategy)
Supondo que você tenha uma API de ouvinte que processe dados por bloco, há dois tipos de eventos: (1) um evento de dados de bloco pronto; (2) evento de fim de processamento. do seguinte modo:
interface MyEventListener<T> {
void onDataChunk(List<T> chunk);
void processComplete();
}
Você pode implementar essa API usando o método create:
Flux.create(sink->{
MyEventListener<T> listener=new MyEventListener<T>(){
@Override
public void onDataChunk(List<T> chunk){
for(T value:chunk){
sink.next(value);
}
}
@Override
public void processComplete(){
sink.complete();
}
};
source.register(listener);
});
Além disso, como create pode ser assíncrono e controlado por backpressure, você pode definir o comportamento de backpressure fornecendo um OverflowStrategy.
- IGNORE: ignora completamente as solicitações de contrapressão downstream, o que pode causar uma IllegalStateException se a fila downstream ficar cheia.
- ERRO: Um IllegalStateException é sinalizado quando o downstream não consegue acompanhar.
- DROP: Descarte este elemento quando o downstream não estiver pronto para receber um novo elemento.
- LATEST: Deixe o downstream obter apenas os elementos mais recentes do upstream.
- BUFFER: (padrão) armazena em buffer todos os elementos que não foram processados a jusante (esse buffer de tamanho ilimitado pode causar OutOfMemoryError).
modo push
No modo push, a fonte de dados enviará dados ativamente para o downstream. Nesse modo, a fonte de dados é o produtor e o downstream é o consumidor. Uma variante de create é push, adequada para gerar fluxos de eventos. Criar 类似,
push também pode ser assíncrono e pode usar as estratégias de estouro acima (
estratégias de estouro) para gerenciar a contrapressão. Apenas um thread de spawn pode chamar next, complete ou error por vez.
Flux<String> bridge=Flux.push(sink->{
myEventProcessor.register(new SingleThreadEventListener<String>(){
public void onDataChunk(List<String> chunk){
for(String s:chunk){
sink.next(s);
}
}
public void processComplete(){
sink.complete();
}
public void processError(Throwable e){
sink.error(e);
}
});
});
Modo híbrido empurrar/puxar (empurrar/puxar)
Ao contrário de push, create pode ser usado no modo push ou pull, portanto, é adequado para APIs de ouvinte de ponte, porque as mensagens de evento virão de forma assíncrona a qualquer momento. O método de retorno de chamada onRequest pode ser registrado no FluxSink
para rastrear solicitações. Esse retorno de chamada pode ser usado para solicitar mais dados da origem ou para gerenciar a contrapressão passando os dados para o coletor quando chega uma solicitação downstream. Este é um padrão push/pull híbrido, porque o downstream pode extrair dados prontos do upstream, e o upstream também pode enviar os dados para o downstream quando estiver pronto.
Flux<String> bridge = Flux.create(sink -> {
myMessageProcessor.register(
new MyMessageListener<String>() {
public void onMessage(List<String> messages) {
for(String s : messages) {
sink.next(s);
}
}
});
sink.onRequest(n -> {
List<String> messages = myMessageProcessor.request(n);
for(String s : message) {
sink.next(s);
}
});
No artigo acima, formas e métodos comuns de geração de fontes de dados são desmontados e listados. Apenas para a conveniência de uma melhor entrada e compreensão, o rigor e a integridade são difíceis de garantir. Se você quiser estudar mais ou sentir que há uma falácia, acesse o site oficial para obter mais informações.
- Endereço do site oficial
- Endereço da versão traduzida para o chinês (a versão do endereço chinês não parece ser a mais recente)