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
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();