Callables and CompletableFuture

Callable Interface

The Callable interface represents a task that can be executed asynchronously and returns a result. It can also throw checked exceptions.

  • Important method: V call() — returns a result of type V and can throw an exception.
  • Typically used with an ExecutorService to submit tasks.
import java.util.concurrent.Callable;

public class MyTask implements Callable<String> {
    @Override
    public String call() throws Exception {
        // Simulate task
        return "Result from Callable";
    }
}Code language: PHP (php)

2. CompletableFuture

CompletableFuture is an extension of the Future interface and is part of the java.util.concurrent package. It provides methods to handle asynchronous computations, allows composing multiple tasks, and handles exceptions gracefully.

  • Important Methods:

  • supplyAsync(): Starts an asynchronous task.
  • thenApply(), thenCombine(), thenAccept(): Chaining operations after task completion.
  • exceptionally(): Handling exceptions in the asynchronous chain.

Program on Callable

This program demonstrates the usage of the Callable interface in combination with an ExecutorService to execute a task asynchronously. The task simulates some processing (e.g., network request or database query) and returns a result after a delay.

//CallableDemo.java
import java.util.concurrent.Callable;
import java.util.concurrent.*;
class MyCallable implements Callable<String> {
    private final String message;
    public MyCallable(String message) {
        this.message = message;
    }
    @Override
    public String call() throws Exception {
        // Simulate a task that takes time
        Thread.sleep(2000);
        return "Callable result: " + message;
    }
}

public class CallableDemo {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(1);

        Callable<String> callableTask = new MyCallable("Hello");

        Future<String> future = executor.submit(callableTask);

        // Perform other operations while waiting for the result
        System.out.println("Submitted callable task. Doing other work...");

        // Block and get the result of the future when ready
        String result = future.get();

        System.out.println("Callable result received: " + result);

        executor.shutdown();
    }
}

/*
C:\>javac CallableDemo.java

C:\>java CallableDemo
Submitted callable task. Doing other work...
Callable result received: Callable result: Hello

*/

Program on CompletableFuture

This program demonstrates the usage of the Callable interface in Java to execute tasks asynchronously, with a fixed thread pool provided by an ExecutorService. It simulates a task that performs some time-consuming work (such as data processing or network communication) and returns a result after a delay.

//CompletableFutureDemo.java
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureDemo {

    public static void main(String[] args) throws InterruptedException,ExecutionException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // Simulate a task that takes time
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "CompletableFuture result";
        });

        // Perform other operations while CompletableFuture is running
        System.out.println("Submitted CompletableFuture task. Doing other work...");

        // Block and get the result of the CompletableFuture when ready
        String result = future.get();

        System.out.println("CompletableFuture result received: " + result);
    }
}

/*

C:\>javac CompletableFutureDemo.java

C:\>java CompletableFutureDemo
Submitted CompletableFuture task. Doing other work...
CompletableFuture result received: CompletableFuture result

*/

Using Callable and CompletableFuture in Java provides powerful mechanisms for implementing concurrent and asynchronous programming. By following best practices such as proper error handling, efficient resource management, and leveraging composition and chaining capabilities, developers can build robust and responsive applications that effectively utilize the capabilities of modern multicore processors and I/O-bound operations.

Scroll to Top