public class MyThread implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName()); } } public class Main { public static void main(String[] args) { MyThread mt = new MyThread(); new Thread(mt,"子线程对象").start(); mt.run(); } }
如上面代码。
运行的时候输出:
main
子线程对象
上面输出结果中的"main"是执行mt.run();语句输出的,
而"子线程对象"则是执行.start()语句输出的。
也即前者代表着主进程,后者代表着子进程。
在HotSpot VM上,其实mt.run()几乎总是会比.start()调用的run()要早执行,因为Thread.start()在调用(caller)线程上创建好线程就返回了,紧接着就可以去调用执行tt.m2();而在被调用(callee)的新线程上还要经过一些JVM内部的初始化动作才能跑到指定的入口方法。这并不是Java语言规范或者JVM规范所要求的行为,只是在HotSpot VM这种特定实现上会有这样的特征,所以既不应该当作标准行为去依赖。
简单点说就是:.start()新起一个线程去运行run方法,但是对main这个线程来说,他会继续往下走 执行mt.run(),一个是新起线程去执行,一个是在本线程(已经在执行的线程)执行。(在程序运行时,主线程已经启动并在运行中,而另外起一个线程start表示线程处于就绪状态,还要等JVM机制调用进入运行状态)
当时debug的时候输出的结果却是反过来。可能是:调用start之后,线程只是处于等待调度的“就绪”状态,并没有启动。调试多线程最好用日志,调试器要么只暂停一个线程,要么全部挂起,容易让人困扰的。
如果代码中加一行,如下
new Thread(mt,"子线程对象").start(); Thread.yield(); mt.run();
效果就明显了。
总结自网上。