有人可以解释一下为什么执行后这个程序的输出是如此不同?
首先,课程: 线程扩展java.lang.Thread
public class UsingThreadExtension extends Thread {
public UsingThreadExtension(String s) {
super(s);
}
@Override
public void run() {
for (int i=0; i<5; i++) {
System.out.println(i + " " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
java.lang.Runnable的实现:
public class UsingRunnableImplementation implements Runnable {
@Override
public void run() {
for (int i=0; i<5; i++) {
System.out.println(i + " " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
主要课程:
public class ThreadsExample {
public static void main(String[] args) {
UsingThreadExtension threadA = new UsingThreadExtension("Thread A");
UsingRunnableImplementation runnableImplementation = new UsingRunnableImplementation();
Thread threadB = new Thread(runnableImplementation, "Thread B");
//threadA.start();
threadB.start();
try {
//threadA.join();
threadB.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//threadA.run();
threadB.run();
System.out.println("Main thread says hello!");
}
}
在这个组合输出中是这样的:
0 Thread B
1 Thread B
2 Thread B
3 Thread B
4 Thread B
Main thread says hello!
在评论threadB部分并取消注释threadA之后,有类似的东西:
0 Thread A
1 Thread A
2 Thread A
3 Thread A
4 Thread A
0 main
1 main
2 main
3 main
4 main
Main thread says hello!
有人能告诉我,究竟是什么导致了这种差异?任何提示赞赏。我想,它与threadA中的重写java.lang.Thread.run()方法相关联,但为什么threadB在第二种情况下不会运行runnable?
答案 0 :(得分:4)
第二种情况(threadA.run()
): -
由于threadA
是UsingThreadExtension
类型的引用: -
UsingThreadExtension threadA = new UsingThreadExtension("Thread A");
所以在threadA上调用run
方法就像这样: -
threadA.run();
将仅在主线程中执行UsingThreadExtension
的运行方法。因此,线程的名称在第二个输出的0 main, 1 main, etc.
中是 main 。
第一个案例(threadB.run()
): -
由于threadB
是Thread
类型的引用,仅指向Thread
的实例。
Thread threadB = new Thread(runnableImplementation, "Thread B");
因此,在其上调用 run 方法,如: -
threadB.run();
将仅在main
线程中再次在 Thread类中执行 run()方法覆盖。但是由于 Thread类的 run()方法实际上并没有打印任何东西。因此你没有获得threadB.run()
的任何输出。
答案 1 :(得分:3)
Runnable.run()
没有启动新线程,只是运行方法 - 就像任何其他方法一样。如果要分离新线程,则必须始终使用Thread.start()
(或将Runnable
提交给执行者)。
答案 2 :(得分:0)
当您构造Thread
传递Runnable
实例时,它会将该实例存储在私有字段中。 run()
的默认java.lang.Thread
方法基本上是
if(target != null) target.run();
所以假设在你的线程B中发生的事情是你start()
线程,并且当它在内部完成时{I} target = null
。然后,当您稍后调用线程的run()
方法时,它不再具有对目标Runnable
的引用,因此不会运行它。
如果您反过来这样做,首先在主线程上调用run()
,然后调用start()
,您会看到大量的日志记录。
在extends Thread
情况下,直接覆盖run()
方法,因此绕过此空检查。