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, Future
ela 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 Future
objeto 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.