Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Java run() method work?

Multi-threading in Java is done by defining run() and invoking start().

Start delegates to a native method that launches a thread through operating system routines and run() is invoked from within this newly spawned thread.

When a standalone application is started a main thread is automatically created to execute the main().

Now consider this code -

public class Test extends Thread {
    public static void main(String[] args) throws Exception {
        new Thread(new Test()).start();
        throw new RuntimeException("Exception from main thread");
    }
    public void run() {
        throw new RuntimeException("Exception from child thread");
    }
}

This is the output -

java.lang.RuntimeException: Exception from child thread
    at com.Test.run(Test.java:11)
    at java.lang.Thread.run(Thread.java:662)
java.lang.RuntimeException: Exception from main thread
    at com.Test.main(Test.java:8)

If main() method is launched via a thread why doesn't run() show up at the top of invocation hierarchy?

How could the main thread get spawned without implementing Runnable?

like image 330
Kshitiz Sharma Avatar asked May 26 '12 05:05

Kshitiz Sharma


People also ask

How does run () method in runnable work?

When the object of a class implementing Runnable class is used to create a thread, then the run method is invoked in the thread which executes separately. The runnable interface provides a standard set of rules for the instances of classes which wish to execute code when they are active.

How does run () method is invoked?

The thread run() method is automatically invoked when start() is called upon the thread object. Or, we can also call the run() method directly without calling the start() method, in which case a new thread will not be created, rather the calling thread will execute the run() of the specific thread class.

Why do we need run () and start () method?

As we know that start() and run() are the two important methods of multithreading and one is used to create a new thread while other is used to start executing that thread.

What is the use of run ()?

The Run command on an operating system such as Microsoft Windows and Unix-like systems is used to directly open an application or document whose path is known.


2 Answers

If main() method is launched via a thread why doesn't run() show up at the top of invocation hierarchy?

As others have mentioned, this is because the "main" thread is special. It is not launched through the standard Thread class mechanisms but instead through Java bootstrap code. The public static void main(String[] args) is always run by the main thread from native code.

Another explanation is that there actually maybe a run() method but the way they build the stackframe is hiding it on purpose for the sake of not confusing the user. For example, since you are doing a new Thread(new Test()) then your Test class is actually the target field inside of the Thread. When the background Thread is started then it actually calls Thread.run() which has the code:

public void run() {
    if (target != null) {
        target.run();
    }
}

But we never see the Thread.run() method in the stackframe although it seems like it should be there. The run() method would be in the stackframe if the user overrode it in a Thread superclass. It could be removed by the JDK to improve stackframe output.

Multi-threading in Java is done by defining run() and invoking start().

This is correct but for posterity I thought it was important to realize that your code has a problem. Your Test class should not be extending Thread but instead should be implementing Runnable. It works because Thread implements Runnable.

Either you should implement Runnable and change your code to something like this:

public class Test implements Runnable {
    public static void main(String[] args) throws Exception {
        new Thread(new Test()).start();
        throw new RuntimeException("Exception from main thread");
    }
    public void run() {
        throw new RuntimeException("Exception from child thread");
    }
}

Or you still extend Thread and change the way you start your thread to something like the following. The above Runnable pattern is recommended since it allows your Test thread to extend another class if necessary.

public class Test extends Thread {
    public static void main(String[] args) throws Exception {
        new Test().start();
        throw new RuntimeException("Exception from main thread");
    }
    @Override
    public void run() {
        throw new RuntimeException("Exception from child thread");
    }
}

Why is this important? You current code is actually instantiates 2 Thread objects but only one of them is start()ed and is running as a background Thread. You could have something like the following bug:

public class Test extends Thread {
    public static void main(String[] args) throws Exception {
        Test test = new Test(); 
        new Thread(test).start();
        // this is not interrupting the background thread
        test.interrupt();
like image 136
Gray Avatar answered Oct 08 '22 16:10

Gray


I haven't looked at the internals of the JVM, but I would guess that the JVM instantiates the main thread to run the main method, but runs this main thread by invoking native code directly, without going through the classical Java classes and methods to start the thread.

like image 42
JB Nizet Avatar answered Oct 08 '22 16:10

JB Nizet