Java Concurrency : Callable
Tags: java, concurrency, multithreading
Published: 2023-09-11 06:39:00

In the last post in this series, we understood what a _Runnable_ is in Java. Some of you may have noticed a big limitation of the _Runnable_ API, that it does not return a value. This means that while you can use a _Runnable_ to execute some unit of work in a separate thread, there isn't a straightforward way for you to retrieve a meaningful value which may represent the result of that work.

For the reader's understanding, the code below shows one way how you might retrieve the result of a _Runnable_. However, please note that this is just for your understanding and you will not find code like this in production grade applications.

```
    public static void main(String[] args) {
        System.out.println("Main method has started.");

        BlockingQueue<String> resultsHolder = new ArrayBlockingQueue<String>(10);

        new Task(resultsHolder);
        new Task(resultsHolder);
        new Task(resultsHolder);

        try {
            System.out.println(resultsHolder.take());
            System.out.println(resultsHolder.take());
            System.out.println(resultsHolder.take());
        } catch (InterruptedException e) {
            // thrown when current thread was interrupted while waiting on the blocking call .take()
            throw new RuntimeException(e);
        }

        System.out.println("Main method has finished.");
    }

    private static class Task extends Thread {

        private static int numTasks;
        private final int id;
        private final BlockingQueue<String> resultsHolder;

        public Task(BlockingQueue<String> resultsHolder) {
            this.id = ++numTasks;
            this.resultsHolder = resultsHolder;
            this.start();
        }

        @Override
        public void run() {
            System.out.println("Task has started.");

            try {
                TimeUnit.MILLISECONDS.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            String result = "Hello, World! This is Task : " + id;
            this.resultsHolder.add(result);

            System.out.println("Task has finished.");
        }
    }
```

Java Concurrency Framework provides the [_Callable_](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html) interface. Along with certain other differences and advantages (more about this in another post), It solves the above mentioned limitation of _Runnable_.

To execute a _Callable_ task, you can use an [_ExecutorService_](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html) to get a [_Future_](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html) representing the result of the task. (More about _Future_ and _ExecutorService_ in another post)

```
    public static void main(String[] args) {
        System.out.println("Main method has started.");

        Task t1 = new Task();
        Task t2 = new Task();
        Task t3 = new Task();

        ExecutorService executorService = Executors.newFixedThreadPool(3);

        Future<String> f1 = executorService.submit(t1);
        Future<String> f2 = executorService.submit(t2);
        Future<String> f3 = executorService.submit(t3);

        try {
            System.out.println(f1.get());
            System.out.println(f2.get());
            System.out.println(f3.get());
        } catch (InterruptedException e) {
            // thrown when current thread was interrupted
            // while waiting on the blocking call .get()
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            // thrown when attempting to retrieve the result
            // of a task that aborted by throwing an exception.
            throw new RuntimeException(e);
        }

        executorService.shutdown();

        System.out.println("Main method has finished.");
    }

    private static class Task implements Callable<String> {

        private static int numTasks;
        private final int id;

        public Task() {
            this.id = ++numTasks;
        }

        @Override
        public String call() {
            System.out.println("Task has started.");

            try {
                TimeUnit.MILLISECONDS.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            return "Hello, World! This is Task : " + id;
        }
    }
```
The output is

```
Main method has started.
Task has started.
Task has started.
Task has started.
Hello, World! This is Task : 1
Hello, World! This is Task : 2
Hello, World! This is Task : 3
Main method has finished.
```

In addition to _Callables_, An _ExecutorService_ can also be used for executing _Runnables_.

The _ExecutorService_ provides these methods for this purpose. Do check these out!

- `void execute(Runnable command)` [[Java Doc Link](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-)]
- `Future<?> submit(Runnable task)` [[Java Doc Link](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#submit-java.lang.Runnable-)]