Главный метод запускается в отдельном потоке JVM, это родительский поток дочернего потока, вот почему вы не видите дочерний поток в верхней части иерархии вызовов.
Итак, в вашем случае JVM создал поток, запускающий вашу программу, которая также расширяет Thread.
Тогда в вашем основном методе вы создали новый экземпляр своего класса, который называется start on it. Это запустит новый поток, который является дочерним потоком, запущенным JVM для запуска вашей программы.
Поскольку основной метод является отправной точкой для автономной java-программы, это ответственность JVM за запуск в отдельном потоке, вы не записываете для него код.
При запуске программы путем вызова основного метода JVM не нуждается в том, чтобы быть потоком или реализовать Runnable, это стандартная процедура.
Описание от Inside Java Virtual Machine
Основной метод() начального класса приложений 'служит в качестве отправной точки для начального потока, который приложения. Начальная линия может, в свою очередь, отключать другие потоки.
В виртуальной машине Java потоки представлены в двух вариантах: daemon и не-демона. Нить демона обычно представляет собой поток, используемый самой виртуальной машиной , такой как поток, который выполняет сбор мусора . Однако приложение может отмечать любые потоки, которые он создает как потоки демона. Начальный поток приложения - тот, который начинается с main() - это поток не-демона.
Приложение для Java продолжает выполняться (экземпляр виртуальной машины продолжает жить), пока все потоки не-демона по-прежнему работают . Когда все не-демонные потоки приложения Java завершатся, экземпляр виртуальной машины выйдет. Если это разрешено администратором безопасности , приложение также может вызвать собственную кончину, вызвав метод exit() класса Runtime или System .
Иерархия вызовов не регулируется вами, она управляется основным планировщиком потоков.
Так, например, если я запускаю тот же код на моей машине Это выход
Exception in thread "main" java.lang.RuntimeException: Exception from main thread
at TestThread.main(TestThread.java:6)
Exception in thread "Thread-1" java.lang.RuntimeException: Exception from child thread
at TestThread.run(TestThread.java:9)
at java.lang.Thread.run(Thread.java:662)
так, когда вы запускали свой пример, планировщик выбрать отпустить ребенка нить, прежде чем основной.
Добавление к @JB Nizet, как будет вызываться программа или как будет реализован жизненный цикл потока, зависит от базовой ОС и аппаратного обеспечения, которая будет и будет меняться.
Никакие детали реализации не предоставили бы полного ответа, каждая реализация будет отличаться.
Чтобы уточнить, о чем вы спрашиваете: ваше ожидание, что 'main()' вызывается по-разному, когда его собственный класс реализует «Runnable»? (Потому что это не так.) – cheeken