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'