How does Java run() method work?

后端 未结 4 705
陌清茗
陌清茗 2021-02-15 10:04

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

4条回答
  •  粉色の甜心
    2021-02-15 10:53

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

提交回复
热议问题