Diferença entre CompletableFuture, Future e RxJava's Observable


193

Gostaria de saber a diferença entre CompletableFuture, Futuree Observable RxJava.

O que eu sei é que todos são assíncronos, mas

Future.get() bloqueia o fio

CompletableFuture fornece os métodos de retorno de chamada

RxJava Observable--- semelhante a CompletableFutureoutros benefícios (não tenho certeza)

Por exemplo: se as necessidades do cliente para fazer várias chamadas de serviço e quando usamos Futures(Java) Future.get()será executado sequencialmente ... gostaria de saber como o seu melhor em RxJava ..

E a documentação http://reactivex.io/intro.html diz

É difícil usar futuros para compor de maneira ideal fluxos de execução assíncronos condicionais (ou impossíveis, pois as latências de cada solicitação variam em tempo de execução). Isso pode ser feito, é claro, mas rapidamente se torna complicado (e, portanto, propenso a erros) ou bloqueia prematuramente o Future.get (), que elimina o benefício da execução assíncrona.

Realmente interessado em saber como RxJavaresolve esse problema. Achei difícil de entender a partir da documentação.


Você leu a documentação de cada um? Não conheço totalmente o RxJava, mas a documentação parece extremamente completa à primeira vista. Não parece particularmente comparável aos dois futuros.
21816 FThompson #

Eu tenho ido através, mas não capaz de obter o quão diferente é a partir futuros Java ... me corrigir se estou errado
shiv455

Como os observáveis ​​são semelhantes aos futuros?
FThompson

2
gostaria de saber onde é diferente, como é diferente no gerenciamento de threads? EX: Future.get () bloqueia o segmento .... como ele será tratado no Observable ???
shiv455

2
pelo menos é um pouco confuso para mim ... uma diferença de alto nível seria realmente útil!
shiv455

Respostas:


278

Futuros

Os futuros foram introduzidos em Java 5 (2004). Eles são basicamente espaços reservados para o resultado de uma operação que ainda não foi concluída. Quando a operação terminar, Futureela conterá esse resultado. Por exemplo, uma operação pode ser uma instância Runnable ou Callable submetida a um ExecutorService . O remetente da operação pode usar o Futureobjeto para verificar se a operação é Concluída () ou aguardar que ela termine usando o método de bloqueio get () .

Exemplo:

/**
* A task that sleeps for a second, then returns 1
**/
public static class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        Thread.sleep(1000);
        return 1;
    }

}

public static void main(String[] args) throws Exception{
    ExecutorService exec = Executors.newSingleThreadExecutor();
    Future<Integer> f = exec.submit(new MyCallable());

    System.out.println(f.isDone()); //False

    System.out.println(f.get()); //Waits until the task is done, then prints 1
}

CompletableFutures

Os CompletableFutures foram introduzidos no Java 8 (2014). Eles são, de fato, uma evolução dos futuros regulares, inspirados no Listenable Futures do Google , parte da biblioteca Guava . Eles são futuros que também permitem que você encadeie tarefas em uma cadeia. Você pode usá-los para dizer a algum segmento de trabalho que "faça alguma tarefa X e, quando terminar, faça outra coisa usando o resultado de X". Usando CompletableFutures, você pode fazer algo com o resultado da operação sem realmente bloquear um thread para aguardar o resultado. Aqui está um exemplo simples:

/**
* A supplier that sleeps for a second, and then returns one
**/
public static class MySupplier implements Supplier<Integer> {

    @Override
    public Integer get() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            //Do nothing
        }
        return 1;
    }
}

/**
* A (pure) function that adds one to a given Integer
**/
public static class PlusOne implements Function<Integer, Integer> {

    @Override
    public Integer apply(Integer x) {
        return x + 1;
    }
}

public static void main(String[] args) throws Exception {
    ExecutorService exec = Executors.newSingleThreadExecutor();
    CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new MySupplier(), exec);
    System.out.println(f.isDone()); // False
    CompletableFuture<Integer> f2 = f.thenApply(new PlusOne());
    System.out.println(f2.get()); // Waits until the "calculation" is done, then prints 2
}

RxJava

RxJava é uma biblioteca inteira para programação reativa criada na Netflix. À primeira vista, parecerá semelhante aos fluxos do Java 8 . É, exceto que é muito mais poderoso.

De maneira semelhante ao Futuros, o RxJava pode ser usado para encadear várias ações síncronas ou assíncronas para criar um pipeline de processamento. Diferentemente dos futuros, que são de uso único, o RxJava funciona em fluxos de zero ou mais itens. Incluindo fluxos intermináveis ​​com um número infinito de itens. Também é muito mais flexível e poderoso, graças a um conjunto incrivelmente rico de operadores .

Diferentemente dos fluxos do Java 8, o RxJava também possui um mecanismo de contrapressão , que permite lidar com casos em que diferentes partes do seu pipeline de processamento operam em diferentes segmentos, a taxas diferentes .

A desvantagem do RxJava é que, apesar da documentação sólida, é uma biblioteca desafiadora para aprender devido à mudança de paradigma envolvida. O código Rx também pode ser um pesadelo para a depuração, especialmente se houver vários threads envolvidos, e ainda pior - se a contrapressão for necessária.

Se você quiser participar, há uma página inteira de vários tutoriais no site oficial, além da documentação oficial e do Javadoc . Você também pode dar uma olhada em alguns vídeos como este, que apresenta uma breve introdução ao Rx e também fala sobre as diferenças entre Rx e Futuros.

Bônus: Fluxos Reativos Java 9

O Reactive Streams do Java 9, também conhecido como Flow API, é um conjunto de interfaces implementadas por várias bibliotecas de fluxos reativos , como RxJava 2 , Akka Streams e Vertx . Eles permitem que essas bibliotecas reativas se interconectem, preservando a importante contrapressão.


Seria bom para dar exemplo de código de como Rx faz isso
Zinan Xing

Então, usando Fluxos Reativos, podemos misturar RxJava, Akka e Vertx em um aplicativo?
IgorGanapolsky 5/17

1
@IgorGanapolsky Sim.
Malt

Em CompletableFutures, usamos métodos de retorno de chamada, esses métodos de retorno de chamada também serão bloqueados se a saída de um método for entrada de outro retorno de chamada. Como bloco futuro com a chamada Future.get (). Por que se diz que Future.get () está bloqueando a chamada enquanto CompletableFutures não bloqueia. Por favor, explique
Deepak

1
@Federico Sure. Cada Futureum é um espaço reservado para um único resultado que pode ou não ter sido concluído ainda. Se você executar a mesma operação novamente, receberá uma nova Futureinstância. O RxJava lida com fluxos de resultados que podem surgir a qualquer momento. Portanto, uma série de operações pode retornar um único observável RxJava que produzirá vários resultados. É um pouco como a diferença entre um único envelope postal e um tubo pneumático que continua bombeando correio.
Malt

20

Trabalho com Rx Java desde a versão 0.9, agora na 1.3.2 e em breve migrando para a 2.x. Uso-a em um projeto privado, onde já trabalho há 8 anos.

Eu não iria mais programar sem essa biblioteca. No começo, eu era cético, mas é um outro estado mental completo que você precisa criar. Quiete difícil no começo. Às vezes eu olhava as bolinhas por horas .. lol

É apenas uma questão de prática e realmente conhecer o fluxo (também conhecido como contrato de observáveis ​​e observadores). Quando você chegar lá, você odiará fazer o contrário.

Para mim, não há realmente uma desvantagem nessa biblioteca.

Caso de uso: Eu tenho uma exibição de monitor que contém 9 medidores (CPU, mem, rede, etc ...). Ao iniciar a visualização, a visualização se inscreve em uma classe de monitor do sistema que retorna um observável (intervalo) que contém todos os dados para os 9 metros. Ele enviará a cada segundo um novo resultado para a visualização (para que não seja pesquisado !!!). Esse observável usa um mapa plano para buscar simultaneamente (de forma assíncrona!) Dados de 9 fontes diferentes e compactar o resultado em um novo modelo que sua visualização exibirá no onNext ().

Como diabos você vai fazer isso com futuros, completáveis ​​etc ... Boa sorte! :)

O Rx Java resolve muitos problemas de programação para mim e torna muito mais fácil ...

Vantagens:

  • Statelss !!! (coisa importante a mencionar, mais importante talvez)
  • Gerenciamento de threads pronto para uso
  • Crie sequências que tenham seu próprio ciclo de vida
  • Tudo é observável, então o encadeamento é fácil
  • Menos código para escrever
  • Jar único no caminho de classe (muito leve)
  • Altamente concorrente
  • Não há mais retorno de chamada
  • Baseado no assinante (contrato restrito entre consumidor e produtor)
  • Estratégias de contrapressão (disjuntor semelhante)
  • Tratamento e recuperação de erros esplêndidos
  • Documentação muito boa (bolinhas de gude <3)
  • Controle completo
  • Muito mais ...

Desvantagens: - Difícil de testar


13
~ " Eu não programaria mais sem essa biblioteca. " Então o RxJava é o final de tudo para todos os projetos de software?
IgorGanapolsky 5/17

É útil mesmo que eu não tenha eventos de Fluxo de Assíncrono?
Mukesh Verma
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.