What if we call run() method directly instead start() method?

We can call run() method if we want but then it would behave just like a normal method and we would not be able to take the advantage of multithreading. When the run method gets called though start() method then a new separate thread is being allocated to the execution of run method, so if more than one thread calls start() method that means their run method is being executed by separate threads (these threads run simultaneously).

On the other hand if the run() method of these threads are being called directly then the execution of all of them is being handled by the same current thread and no multithreading will take place, hence the output would reflect the sequential execution of threads in the specified order. Did it confuse you? Lets have a look at the below code to understand this situation.

  • Each thread starts in a separate call stack.

  • Invoking the run() method from main thread, the run() method goes onto the current call stack rather than at the beginning of a new call stack.

What happens when a function is called?

When a function is called the following operations take place:

  1. The arguments are evaluated.

  2. A new stack frame is pushed into the call stack.

  3. Parameters are initialized.

  4. Method body is executed.

  5. Value is retured and current stack frame is popped from the call stack.

he purpose of start() is to create a separate call stack for the thread. A separate call stack is created by it, and then run() is called by JVM.

Let us see what happens if we don’t call start() and rather call run() directly. We have modified the first program discussed here.

class Test1 extends Thread { public void run() { try { // Displaying the thread that is running System.out.println ("Thread " + Thread.currentThread().getId() + " is running"); } catch (Exception e) { // Throwing an exception System.out.println ("Exception is caught"); } } } // Main Class public class Test { public static void main(String[] args) { int n = 8; for (int i=0; i<n; i++) { Test1 object = new Test1(); // start() is replaced with run() for // seeing the purpose of start object.run(); } } }

Thread 1 is running Thread 1 is running Thread 1 is running Thread 1 is running Thread 1 is running Thread 1 is running Thread 1 is running Thread 1 is running
class Test extends Thread { public void run(){ System.out.println("running..."); } public static void main(String args[]) { Test t1=new Test(); t1.run();//fine, but does not start a separate call stack } }

Calling run() method
public class Test implements Runnable { public void run(){ for(int i=1;i<=3;i++) { try{ Thread.sleep(1000); }catch(InterruptedException ie){ ie.printStackTrace(); } System.out.println(i); } } public static void main(String args[]){ Thread th1 = new Thread(new Test(), "th1"); Thread th2 = new Thread(new Test(), "th2"); th1.run(); th2.run(); } }

1 2 3 1 2 3

As you can observe in the output that multithreading didn’t place here, it because both the run methods are being handled by the current thread. that treated them like normal methods and had them executed in the specified order rather then having them executed simultaneously. Thread scheduler didn’t play any role here.

Problem if you direct call run() method
class Test extends Thread{ public void run(){ for(int i=1;i<5;i++){ try{Thread.sleep(500);}catch(InterruptedException e) {System.out.println(e);} System.out.println(i); } } public static void main(String args[]){ Test t1=new Test(); Test t2=new Test(); t1.run(); t2.run(); } }

1 2 3 4 1 2 3 4
Calling start() method

Multithreading takes place and the output reflects simultaneous execution of threads.

public class RunMethodExample2 { public void run(){ for(int i=1;i<=3;i++){ try{ Thread.sleep(1000); } catch(InterruptedException ie){ ie.printStackTrace(); } System.out.println(i); } } public static void main(String args[]){ Thread th1 = new Thread(new RunMethodExample(), "th1"); Thread th2 = new Thread(new RunMethodExample(), "th2"); th1.start(); th2.start(); } }

1 1 2 2 3 3
Points to note
  • When we call start() method on the thread it causes the thread to begin execution.

  • run() method of the thread is called by the Java Virtual Machine.

  • If we directly call run method it will be treated as a normal overridden method of the thread class (or runnable interface) and it will be executed with in the context of the current thread not in a new thread.