Java Callable and Future

Introduction

Callable and Future are part of the java.util.concurrent package and are used for concurrent programming. Callable is similar to Runnable, but it can return a result and throw a checked exception. Future represents the result of an asynchronous computation and provides methods to check if the computation is complete, to wait for its completion, and to retrieve the result.

Key Points:

  • Callable: An interface that defines a task that returns a result and can throw a checked exception.
  • Future: An interface that represents the result of an asynchronous computation.
  • Concurrency Utilities: Part of the java.util.concurrent package, which provides robust concurrency utilities.

Table of Contents

  1. Creating a Callable Task
  2. Submitting Callable Tasks to ExecutorService
  3. Using Future to Retrieve Results
  4. Comprehensive Example
  5. Real-World Analogy
  6. Conclusion

1. Creating a Callable Task

A Callable task is similar to a Runnable task, but it returns a result and can throw a checked exception.

Example:

import java.util.concurrent.Callable;

public class CallableTask implements Callable<Integer> {
    private int number;

    public CallableTask(int number) {
        this.number = number;
    }

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= number; i++) {
            sum += i;
            Thread.sleep(100);  // Simulate time-consuming task
        }
        return sum;
    }
}

2. Submitting Callable Tasks to ExecutorService

You can submit a Callable task to an ExecutorService and get a Future object that represents the result of the computation.

Example:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CallableFutureExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        CallableTask task = new CallableTask(10);
        Future<Integer> future = executor.submit(task);

        executor.shutdown();
    }
}

3. Using Future to Retrieve Results

The Future interface provides methods to check if the computation is complete, wait for its completion, and retrieve the result.

Example:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

public class CallableFutureExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        CallableTask task = new CallableTask(10);
        Future<Integer> future = executor.submit(task);

        executor.shutdown();

        try {
            Integer result = future.get();  // Wait for the task to complete and retrieve the result
            System.out.println("Result: " + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

4. Comprehensive Example

Example: Using Callable and Future

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.ArrayList;
import java.util.List;

class CallableTask implements Callable<Integer> {
    private int number;

    public CallableTask(int number) {
        this.number = number;
    }

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= number; i++) {
            sum += i;
            Thread.sleep(100);  // Simulate time-consuming task
        }
        return sum;
    }
}

public class CallableFutureExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        List<Future<Integer>> futures = new ArrayList<>();

        for (int i = 1; i <= 5; i++) {
            CallableTask task = new CallableTask(i * 10);
            Future<Integer> future = executor.submit(task);
            futures.add(future);
        }

        executor.shutdown();

        for (Future<Integer> future : futures) {
            try {
                Integer result = future.get();  // Wait for the task to complete and retrieve the result
                System.out.println("Result: " + result);
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}

Output:

Result: 55
Result: 210
Result: 465
Result: 820
Result: 1275

5. Real-World Analogy

Consider a scenario where multiple students (threads) are given different assignments (tasks) to complete. Each student works on their assignment and once they finish, they submit it to the teacher (ExecutorService). The teacher then collects all the completed assignments (Future) and checks the results.

6. Conclusion

Callable and Future are powerful interfaces in the java.util.concurrent package that provide a way to execute tasks asynchronously and retrieve their results. By using these interfaces, you can manage complex concurrent tasks more efficiently and handle their results in a structured manner.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top