Runnable

Java Runnable Example

In this example, we will take a look into the Runnable interface in Java, and how it can be used in association with the Thread class to create and execute new threads in your program. We will also try to explain what a Runnable is and what’s the difference from Thread, as well as take a look into the different ways that you can implement Runnable in your code.

1. Runnables and Threads

Let’s start by talking about a very common confusion in Java. Runnables are NOT Threads. The Runnable interface is used to define a certain task that we want to execute, and the whole implementation of this task is inside its only method, run() (which accepts no arguments). The Runnable class by itself does not create a separate thread, because this is what Thread actually does.

Thread is used to create a new execution path (a new thread), separate from the main program. By providing a Runnable as an argument to a Thread constructor, you are essentially giving access of the Runnable’s task (defined in the run() method), to a new Thread object. At any time during your program, you can start the new thread, by using Thread.start() and the Runnable’s code will start running.

2. Why use Runnable?

Although you have the ability to create new threads by using just the Thread class, which by itself implements the Runnable interface, the suggested and much more accepted approach is to use Runnable for all the logic that we want to provide for our threads. There are certain reasons for that:

  • Modularity: When you run a thread and it finishes running, there is no way to restart it. This could lead to a lot of code duplication in case of multithreading, where you need a certain task to run a number of times. Fortunately, you can create a Runnable instance which can be reused in any number of threads.
  • Ease of use: Runnable only has one method, public void run(). It accepts no arguments and is as simple as possible. Thread has many methods that need to be taken into account making it very cumbersome to work with, and the extra overhead is always an issue.
  • Inheritance: More often than not, you will have to use additional classes (through inheritance) to extend the functionality of your Runnable object. Java does not support multiple inheritance, so it is much more convenient to create a new class which just implements Runnable (and allows to extend another class) than creating a new class that extends Thread and prevents you from inheriting anything else.

3. Runnable implementation and example

There are two ways to implement a Runnable in Java. Let’s take a quick look into them:

  • Inheritance: You can create a class which implements the Runnable interface. You will be forced to implement the run() method, which contains the logic/code of the task, and instantiate it in the standard Java way. You can use pass this as an argument to a Thread instance, as explained above.
  • Anonymous inner class: In some cases you need to run a small snippet of only a few lines of code. In that case, you can always create a new anonymous inner class inside the Thread constructor and implement the run() method there as well. This is of course not modular, and you cannot reuse that code.

Let’s take a look at the code and see both of these ways at work!

MyRunnableImplementation.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
package com.javacodegeeks.runnableexample;
 
public class MyRunnableImplementation implements Runnable {
 
    // We are creating anew class that implements the Runnable interface,
    // so we need to override and implement it's only method, run().
    @Override
    public void run() {
         
        // We are creating a simple loop which will run and allow us to take
        // a look into how the different threads run.
        for (int i = 0; i < 5; i++) {
             
            // Thread.currentThread().getName() is used to get the name of the
            // currently running thread. We can provide a name, if we create
            // the thread ourselves, else it will be given one from the JVM.
            System.out.println(Thread.currentThread().getName() +
                    "\twith Runnable: MyRunnableImplementation runs..." + i);
        }
    }
}

As you can see, we create a class that implements the Runnable interface. In the main program, we will instantiate this class and pass it as an argument to a Thread constructor, which will run the task, which in this context is the loop.

RunnableExampleMain.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.javacodegeeks.runnableexample;
 
 
public class RunnableExampleMain {
 
    public static void main(String[] args) {
        System.out.println("Executing program...");
         
        // Create a new instance of our class that implements the Runnable interface.
        // This class can be provided as an argument to a Thread instance.
        MyRunnableImplementation r = new MyRunnableImplementation();
         
        // Create a new Thread instance, provide the task that we want to run
        // (by providing the Runnable as an argument) and give the thread a name.
        // Now we can use Thread.start() to run it!
        Thread thread1 = new Thread(r, "Thread 1");
        thread1.start();
         
        // We are creating a second thread. Take notice that we are
        // providing the same Runnable, so this thread will run the same task
        // as the first one.
        Thread thread2 = new Thread(r, "Thread 2");
        thread2.start();
 
        // Create a thread and provide the Runnable argument as an anonymous inner class.
        // Since we are creating the class "on the spot", we need to provide the implementation
        // of the run() method here.
        // This way is faster and more compact, but it lacks reusability.
        Thread thread3 = new Thread(new Runnable() {
            @Override
            public void run() {
                 
                // We are doing the same thing as with the MyRunnableImplementation class
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() +
                            "\twith Runnable: Inner class Runnable runs..." + i);
                }
            }
        }, "Thread 3");
        thread3.start();
    }
}

Take notice here, that we can use the same Runnable on more than one Thread, without an issue. Also, we can implement the Runnable anonymously inside the constructor.

3.1 Java Runnable Example – Output

We have to take into consideration the fact that we are talking about different threads here, which are unpredictable by definition. Depending on the JVM implementation and the running platform’s architecture, the threads can run in any order. In our example specifically, you can see different output variations, because although the threads run concurrently (so when you invoke Thread.start() a new thread starts running in parallel to your main program),  they all have the task to print something to the standard output, and we have no way of knowing which thread will use the output at any given time.

Let’s take a look at two different runs, where we can easily see which thread runs and which Runnable they are using:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Executing program...
Thread 1    with Runnable: MyRunnableImplementation runs...0
Thread 1    with Runnable: MyRunnableImplementation runs...1
Thread 1    with Runnable: MyRunnableImplementation runs...2
Thread 1    with Runnable: MyRunnableImplementation runs...3
Thread 1    with Runnable: MyRunnableImplementation runs...4
Thread 2    with Runnable: MyRunnableImplementation runs...0
Thread 2    with Runnable: MyRunnableImplementation runs...1
Thread 2    with Runnable: MyRunnableImplementation runs...2
Thread 2    with Runnable: MyRunnableImplementation runs...3
Thread 2    with Runnable: MyRunnableImplementation runs...4
Thread 3    with Runnable: Inner class Runnable runs...0
Thread 3    with Runnable: Inner class Runnable runs...1
Thread 3    with Runnable: Inner class Runnable runs...2
Thread 3    with Runnable: Inner class Runnable runs...3
Thread 3    with Runnable: Inner class Runnable runs...4

Pretty standard, the output is what someone would possibly expect. Take notice that the two first threads used the same instance of MyRunnableImplementation with no issues, while the third one used the inner class. However, after running it again for a couple of times, we got this output:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Executing program...
Thread 1    with Runnable: MyRunnableImplementation runs...0
Thread 1    with Runnable: MyRunnableImplementation runs...1
Thread 1    with Runnable: MyRunnableImplementation runs...2
Thread 1    with Runnable: MyRunnableImplementation runs...3
Thread 1    with Runnable: MyRunnableImplementation runs...4
Thread 3    with Runnable: Inner class Runnable runs...0
Thread 3    with Runnable: Inner class Runnable runs...1
Thread 3    with Runnable: Inner class Runnable runs...2
Thread 2    with Runnable: MyRunnableImplementation runs...0
Thread 2    with Runnable: MyRunnableImplementation runs...1
Thread 3    with Runnable: Inner class Runnable runs...3
Thread 3    with Runnable: Inner class Runnable runs...4
Thread 2    with Runnable: MyRunnableImplementation runs...2
Thread 2    with Runnable: MyRunnableImplementation runs...3
Thread 2    with Runnable: MyRunnableImplementation runs...4

Pretty cool, right? Well, yes, but threads can sometimes cause a real headache, and in many cases, you need to know in which order they run. Luckily, Java contains ways of achieving synchronization and scheduling, which are out of the scope of this tutorial.

4. Download the source code

In this example, we learned the Runnable interface in Java, and how it can be used in association with the Thread class to create and execute new threads in your program.

This was an example of the Runnable interface in Java.

Download
Download the Eclipse project of this tutorial here: Java Runnable Example

Last updated on Apr. 28th, 2020

Ilias Koutsakis

Ilias has graduated from the Department of Informatics and Telecommunications of the National and Kapodistrian University of Athens. He is interested in all aspects of software engineering, particularly data mining, and loves the challenge of working with new technologies. He is pursuing the dream of clean and readable code on a daily basis.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
K.Srihari venkatesh
K.Srihari venkatesh
4 years ago

The programs in site are very diificult to understand.

threadripper
threadripper
4 years ago

I think the output is a bit misleading. It’s possible to have output like this, if we only look at thread1 and thread2:

Thread 2   with Runnable: MyRunnableImplementation runs…0
Thread 2   with Runnable: MyRunnableImplementation runs…1
Thread 2   with Runnable: MyRunnableImplementation runs…2
Thread 2   with Runnable: MyRunnableImplementation runs…3
Thread 1   with Runnable: MyRunnableImplementation runs…0
Thread 2   with Runnable: MyRunnableImplementation runs…4
Thread 1   with Runnable: MyRunnableImplementation runs…1
Thread 1   with Runnable: MyRunnableImplementation runs…2
Thread 1   with Runnable: MyRunnableImplementation runs…3
Thread 1   with Runnable: MyRunnableImplementation runs…4

The order is not guaranteed. T2 is NOT ran after T1. All three threads in the example can have order scrambled.

Declan
Declan
1 year ago

Also, ease-of-unit-testing, is another reason for the Runnable approach.

Back to top button