Future And Callable
Callable
is a function that will be executed asynchronously that can be used to submit to a Thread
Future is the result of this asynchronous function
Callable
Can be used to create a function to be call.
For example, we have
public static void main(String[] args) {
try {
Integer result = myCallableFunction().call();
System.out.println("result: " + result);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Callable<Integer> myCallableFunction() {
return () -> {
System.out.printf("%s working on this%n", Thread.currentThread().getName());
Thread.sleep(5000);
System.out.printf("%s finished on this%n", Thread.currentThread().getName());
return 5;
};
}
As a result we have
main working on this
main finished on this
result: 5
[!note]
This is still being executed synchronously
Future
To have a Future
we need to make our Callable
to be executed asynchronously.
CompletableFuture
One way is to use the CompletableFuture
that will use a thread in java Common Pool
public static void main(String[] args) {
Future<Integer> result = myCallableFunction();
System.out.println("Some code executed in between");
try {
System.out.println("result: " + result.get());
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
public static CompletableFuture<Integer> myCallableFunction() {
return CompletableFuture.supplyAsync(() -> {
System.out.printf("%s working on this%n", Thread.currentThread().getName());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.printf("%s finished on this%n", Thread.currentThread().getName());
return 5;
});
}
In here, the callable function is wrapped with CompletableFuture.supplyAsync
as a Supplier
. As a result, this function will be executed on its own thread.
As a result, we have the following:
Some code executed in between
ForkJoinPool.commonPool-worker-1 working on this
ForkJoinPool.commonPool-worker-1 finished on this
result: 5
[!note]
Note thatCallable
does not work withCompletableFuture.supplyAsync
directly. In the example above, we used the same code inCallable
as theSupplier
insidesupplyAsync
. However,Callable
does work withExecutorService
directly
ExecutorService
ExecutorService
works with Callable
directly. The submit()
function takes in a Callable
and returns a Future
.
<T> Future<T> submit(Callable<T> task);
For example:
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<?> result = executorService.submit(() -> process());
executorService.shutdown();
try {
System.out.println("result: " + result.get());
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
public static int process() {
int random = (new Random()).nextInt(5000);
System.out.printf("%s working on this for %s%n" , Thread.currentThread().getName(), random);
try {
Thread.sleep(random);
} catch (InterruptedException exception) {
exception.printStackTrace();
}
return random;
}
[!note]
When we callresult.get()
in both scenario ofCompletableFuture.supplyAsync
orExecutorService
, the thread block indefinitely until it gets the result.
As a result, we have the following logs:
pool-1-thread-1 working on this for 2447
result: 2447
Note that in here we're not using the Common Pool anymore in contrast to the previous method.