Runnable vs Callable – Find out the differences

Posted by Marta on February 2, 2023 Viewed 2366 times

Card image cap

In this article you will learn what is a runnable , what is a callable and the difference between the two in java, runnable vs callable. These concepts are important when you are dealing with concurrency.

Concurrency basically means there is not just one execution thread in your program, but several executions or threads, potentially happening simultaneously. Therefore different pieces of the code might be executed at the same time. 

To illustrate the runnable and callable concepts I have included several examples throughout the article. Let’s get started!

Runnable

The Runnable interface in java enables you to define a block of code that can be executed within its own thread. Therefore if you create several runnable classes and execute them, and you will have several threads running at the same time within the same process or program. This is known as concurrency. 

See the runnable interface below:

public interface Runnable {
    public abstract void run();
}

You can think of runnable as a wrapper class that allow you to define a piece of code that can be executed in isolation. Consequently this task could run in parallel with other tasks.

For example, let’s say you are cooking a rice recipe and you need to chop vegetables and boil rice. You can do these two tasks one after the other one. However if you can do both at the same time, in parallel, you will finish much faster. That’s what runnable allow you to do in java. Define code as isolated task and execute them in parallel. Also runnable allow you to run tasks in the background, to avoid blocking the main execution thread.

Runnable examples

To illustrate how the runnable interface works, see the below examples:

public class WorkRunnable implements Runnable{

        @Override
        public void run() {
            try {

                System.out.println("Task started");

                Thread.sleep(1000);

                String name = Thread.currentThread().getName();
                String state = Thread.currentThread().getState().toString();
                System.out.println("Thread "+name+" with state "+state);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

The code above is quite simple. This runnable class will print Task started to the console. Then wait for one second. And last it will print the name of the thread that has executed the task.

Callable

Next is callable. Callable is also a java interface and as Runnable, you can use it to run tasks in parallel. However there is a key difference. The callable can return the result of the task or throw an exception.

public interface Callable<V> {
    V call() throws Exception;
}

The Callable interface is included in Java to address some of runnable limitations. Let’s say your program is executing a long calculation task defined as a runnable. And you would like to retrieve the calculation result. Since the runnable interface is defined to return void, in other words nothing, you can’t pass back the calculation result directly. You will need to use shared data structure for this purpose. The callable interface solves this problem.

Callable examples

To illustrate how to use Callable, let’s see an example.

public class WorkCallable implements Callable<String>{

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

                Thread.sleep(1000);

                String name = Thread.currentThread().getName();
                String state = Thread.currentThread().getState().toString();
                System.out.println("Thread "+name+" with state "+state);
               
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Task done";
        }
    }

The code above is basically doing the same as the previous example: printing Task started, waiting for 1 second and lastly printing the thread name. But there is one key different, when you implement the class you have to specify the type of the returning variable. In this example the Callable will return a string, however it could return any type you want, included a class you defined.

Let’s see another example of the Callable interface. In this example, I will modify the class WorkCallable so instead of waiting 1000 ms, It will wait for any number of milliseconds that I pass in. To do so, I will add a variable field and a constructor to the WorkCallable class.

public class WorkCallable implements Callable<String> {

        private int millisecondToWait;

        public WorkCallable(int millisecondToWait){
            this.millisecondToWait = millisecondToWait;
        }

        @Override
        public String call() throws Exception{
            try {
                System.out.println("Task started: Waiting for " + millisecondToWait);

                Thread.sleep(millisecondToWait);

                String name = Thread.currentThread().getName();
                String state = Thread.currentThread().getState().toString();
                System.out.println("Thread "+name+" with state "+state);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Task done";
        }
    }

This demonstrates a way of passing input values to the Callable task. This same method can be applied for Runnable as well. This can be useful if you want to define an isolated or independent task that needs depends on some input values. You could see those values as parameter to the Runnable.

Runnable vs Callable – The difference

The main difference between Runnable and Callable is that Callable will return the result of executing the task to the caller. If you use Runnable you can’t return anything, any result will need to be saved in separated shared structure or database. To understand this difference runnable vs callable, you can compare the two interfaces.

public interface Runnable {
    public abstract void run();
}

public interface Callable<V> {
    V call() throws Exception;
}

How to execute a runnable

You know to create a Runnable class. You just need to create a class that implement the Runnable interface. And then fill up the run method with the code snippet that you want to run in a different thread. This will define our task. Now let’s see how to execute the runnable. There are a few ways, using our previous example.

First way is creating an instance of the Runnable class and then call the run method. This will run the code in the main application thread.

new WorkRunnable().run();
System.out.print("End");

Output:

Task started
Thread main with state RUNNABLE
End

As you can see in the code above, the Runnable will finish executing and the next line System.out.print("End"); will be executed. Both statements are executed sequentially because they are executed by one single thread. In this case, the main thread will be blocked and the program is not using concurrency.

Let’s see how to execute the Runnable class in a separated thread.

new Thread(new WorkRunnable()).start();
System.out.println("End");

Output:

Task started
End
Thread Thread-0 with state RUNNABLE

As you can see the thread name is different now. This means the program has created a different execution thread to execute the code contained in the WorkRunnable class. The main thread will trigger the runnable and then continue with the execution. That’s why the text end is printed before the runnable finished its execution.

How to execute a callable

Just like a Runnable, you can execute a Callable in a few different ways.

You can execute it in the main thread, which will blocked the main thread until the Callable execution finished. See how it works below:

new WorkCallable(1000).call();
System.out.println("End");

Output:

Task started: Waiting for 1000
Thread main with state RUNNABLE
End

You can run the Callable in a separate thread. This way won’t block the main thread. However the way to execute a Callable in a separated thread is slightly different than the Runnable way. In this case you will create a thread pool. This thread will be idle until you submit a task to the pool. As soon as you submit the task, the pool will find a thread idle and it will execute the task. See this in action below:

ExecutorService pool = Executors.newCachedThreadPool();
pool.submit(new WorkCallable(1000));
System.out.println("End");

Output:

End
Task started: Waiting for 1000
Thread pool-1-thread-1 with state RUNNABLE

Conclusion

To summarise, in this article we have covered how Runnable and Callable interfaces in java enable you to define code snippet that you can execute in different threads. This allow you to take advantage of the concurrency framework that java provides. Additionally we have seen the different between a Callable and a Runnable, runnable vs callable, and how to execute each of them.

I hope you enjoy the article and thank you so much for reading and supporting this blog! 🙂

More Interesting Articles

Matplotlib guide : Custom a graph – Imshow, Colorbar, etc

Django: order by and filter with examples

What is the use of return in python programming?

How to Count Occurrences in String in Python

DFS in Python – How to Implement it – Ultimate Guide

Project-Based Programming Introduction

Steady pace book with lots of worked examples. Starting with the basics, and moving to projects, data visualisation, and web applications

100% Recommended book for Java Beginners

Unique lay-out and teaching programming style helping new concepts stick in your memory

90 Specific Ways to Write Better Python

Great guide for those who want to improve their skills when writing python code. Easy to understand. Many practical examples

Grow Your Java skills as a developer

Perfect Boook for anyone who has an alright knowledge of Java and wants to take it to the next level.

Write Code as a Professional Developer

Excellent read for anyone who already know how to program and want to learn Best Practices

Every Developer should read this

Perfect book for anyone transitioning into the mid/mid-senior developer level

Great preparation for interviews

Great book and probably the best way to practice for interview. Some really good information on how to perform an interview. Code Example in Java