Future

A result of an asynchronous call. Typically from ExecutorService result. For example

private static String someTask() throws InterruptedException {  
  System.out.printf("Calculating...: %s %n", Thread.currentThread().getName());  
  Thread.sleep(5000);  
  return "hello world";  
}
public static void main(String[] args) throws ExecutionException, InterruptedException {  
  multiThreadExecutorsFuture();  
}
  
private static void multiThreadExecutorsFuture() throws ExecutionException, InterruptedException {  
  ExecutorService executorService = Executors.newCachedThreadPool();  
  Future<String> result = executorService.submit(Main::someTask);  
  System.out.printf("Run here %s %n", Thread.currentThread().getName());  
  System.out.println(result.get());  
  executorService.shutdown();  
}
Run here main 
Calculating...: pool-1-thread-1 
hello world

Single thread Future

A future object can be created independently. For example:

private static void singleThreadFuture() throws ExecutionException, InterruptedException {  
  RunnableFuture<String> future = new FutureTask<>(Main::someTask);  
  future.run();  
  System.out.printf("Run here %s %n", Thread.currentThread().getName());  
  System.out.println(future.get());  
}

public static void main(String[] args) throws ExecutionException, InterruptedException {  
  singleThreadFuture();  
}

Which give us a result:

Calculating...: main 
Run here main 
hello world

In here as we can see that the line Run here won't be executed until the future is completed.

Multi-thread Future

Using Thread

Where Future shines is multi-threaded. We can just launch the RunnableFuture with a thread:

private static void multiThreadFuture() throws ExecutionException, InterruptedException {  
  RunnableFuture<String> future = new FutureTask<>(Main::someTask);  
  Thread thread = new Thread(future);  
  thread.start();  
  System.out.printf("Run here %s %n", Thread.currentThread().getName());  
  System.out.println(future.get());  
}
public static void main(String[] args) throws ExecutionException, InterruptedException {  
  multiThreadFuture();  
}

As a result, this will make it multi-thread

Run here main 
Calculating...: Thread-0 
hello world

and the Run here will run independently from the main thread.

Using ExecutorService

We can also use ExecutorService to run our thread:

private static void multiThreadExecutorsFuture() throws ExecutionException, InterruptedException {  
  ExecutorService executorService = Executors.newCachedThreadPool();  
  Future<String> result = executorService.submit(Main::someTask);  
  System.out.printf("Run here %s %n", Thread.currentThread().getName());  
  System.out.println(result.get());  
  executorService.shutdown();  
}
public static void main(String[] args) throws ExecutionException, InterruptedException {  
  multiThreadExecutorsFuture();  
}
Run here main 
Calculating...: pool-1-thread-1 
hello world

ListenableFuture

ListenableFuture accepts Listener which is like call back when the Future is completed.

private static void listenableFuture() throws ExecutionException, InterruptedException {  
  ExecutorService executorService = Executors.newCachedThreadPool();  
  ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);  
  ListenableFuture<String> result = listeningExecutorService.submit(Main::someTask);  

  // Add a listener here
  result.addListener(() -> System.out.printf("task is done %s%n", Thread.currentThread().getName()), executorService);  

  System.out.printf("Run here %s %n", Thread.currentThread().getName());  
  System.out.println(result.get());  
  listeningExecutorService.shutdown();  
}
public static void main(String[] args) throws ExecutionException, InterruptedException {  
  listenableFuture();  
}
Calculating...: pool-1-thread-1 
Run here main 
hello world
task is done pool-1-thread-2

To use this we need Guava library which is a Google Java library includes a lot of helpers and utilities (google/guava: Google core libraries for Java (github.com))

implementation 'com.google.guava:guava:32.1.3-jre'