Java Thread run() Method with Examples

In Java, you can call the run() method directly on a class that implements the Runnable interface. However, it’s important to understand the distinction between calling run() and start() methods on a thread.

Calling run() Method

When you call the run() method directly on a class that implements Runnable, it simply runs the method in the same calling thread, and there is no separate thread of execution. The run() method behaves like any other method call, and the execution is sequential.

Example:

public class TechVidvanrunmethodDemo {
    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
    	// Calling the run() method directly
    	r.run();
    }
}
class MyRunnable implements Runnable {
    public void run() {
        System.out.println("TechVidvan-Thread is running");
    }
}

Output:

TechVidvan-Thread is running

Calling start() Method:

To create a new thread and execute the run() method in a separate thread of execution, you need to call the start() method on a Thread object. The start() method internally calls the run() method in a new thread, allowing concurrent execution.

Example:

public class Main {
    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
    	Thread t = new Thread(r);
    	// Starting a new thread and calling the run() method in that thread
        t.start();
    }
}
 
class MyRunnable implements Runnable {
    public void run() {
        System.out.println("TechVidvan-Thread is running");
    }
}

Output:

TechVidvan-Thread is running

Overloading the run() method:

Example code:

class BaseRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("BaseRunnable's run() method");
    }
    public void run(String message) {
        System.out.println("CustomRunnable's overloaded run(): " + message);
    }
}
class DataFlair{
    public static void main(String[] args) {
        BaseRunnable baseRunnable = new BaseRunnable();
        baseRunnable.run(); // Output: BaseRunnable's run() method
        baseRunnable.run("Techvidvan run() example"); // Output: BaseRunnable's overloaded run(): Techvidvan run() example
    }
}

Output:

BaseRunnable’s run() method

CustomRunnable’s overloaded run(): Techvidvan run() example

Explanation:

In the above code, the run() method is explicitly called, and the overloaded run(String message) method is also explicitly called. The reason why the run() method is called explicitly is because it’s not automatically called by the Java runtime when an instance of Runnable is used with the Thread class. Instead, the run() method is intended to be invoked by the Thread class when the thread is started.

Calling run() Multiple times:

When you call the run() method on an object of a class that implements the Runnable interface, the method’s code is executed in the current thread, just like any other regular method call. There is no new thread created.

Example Code:

class MyRunnable implements Runnable {
    @Override
    public void run() {
        for(int i=1;i<6;i++) {
            System.out.println("Running " + i + " time");
        }
    }
}
class DataFlair{
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        myRunnable.run(); // This does not create a new thread.
        myRunnable.run(); // It just runs the code sequentially.
    }
}

Output:

Running 1 time

Running 2 time

Running 3 time

Running 4 time

Running 5 time

Running 1 time

Running 2 time

Running 3 time

Running 4 time

Running 5 time

If you do not override the run() method when implementing the Runnable interface, you will still have a class that compiles successfully. However, when you create an instance of this class and pass it to a Thread object to start a new thread, the new thread will have no specific code to execute. Here’s what happens:

Without Overriding run():

If you don’t provide your own implementation of the run() method in the class that implements Runnable, the default run() method of the Runnable interface will be inherited and used. The default run() method does nothing; it’s an empty method. So, when you start a thread using an instance of your class, the thread will execute the default, empty run() method, and the thread will complete immediately.

Example:

Let’s say you have the following class that implements Runnable without overriding the run() method:

class MyRunnable implements Runnable {
    // No custom implementation of run() here
}

And you attempt to use it like this:

public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start(); // The thread starts but doesn't execute any specific code.
    }
}

In this case, the thread will start but immediately finish because the default run() method doesn’t contain any meaningful code.

To achieve actual concurrent execution and customize what a thread does, you must override the run() method in your class that implements the Runnable interface. This allows you to provide specific behavior that the new thread will execute when started.

Summary

In summary, calling the run() method directly on a class that implements Runnable runs the method in the same thread, while calling the start() method on a Thread object creates a new thread and executes the run() method concurrently in that new thread. For true multithreading and parallel execution, use the start() method to create new threads and execute the run() method in separate.