我只是想知道如果我继承了一个扩展Thread
的类并且我编写了以下代码并进行了测试的结果会是什么结果:
class A extends Thread {
public A() {
this.start();
}
public void run() {
System.out.println(" in A " + Thread.currentThread().getName());
}
}
class B extends A {
public void run() {
System.out.println(" in B " + Thread.currentThread().getName());
}
}
public class OverrideRun {
public static void main(String[] args) {
A a = new A();
B b = new B();
}
}
结果是:
在A-Thread-0中 在B Thread-1
中
但我不明白为什么要创建两个线程?
答案 0 :(得分:3)
这是因为B b = new B();
语句不调用类B
的参数参数,并且不调用类A
的参数构造函数(默认)。
这是由于构造函数链接。
答案 1 :(得分:2)
那是因为你创建了两个线程(两个继承自Thread
的对象),这里:
public static void main(String[] args) {
A a = new A(); // #1
B b = new B(); // #2
}
答案 2 :(得分:2)
但我不明白为什么要创建两个线程?
启动了两个线程,因为您在A()
构造函数中启动它们:
public A() {
this.start();
}
并且您正在构建两个对象 - A
和B
扩展A
:
A a = new A();
B b = new B();
默认情况下,当你说new B()
因为它没有no-arg构造函数时,它会调用超类的no-arg构造函数。所以它将调用启动线程的A
构造函数。见Java documentation here。引用:
您不必为您的班级提供任何构造函数,但在执行此操作时必须小心。编译器自动为没有构造函数的任何类提供无参数的默认构造函数。此默认构造函数将调用超类的无参数构造函数。在这种情况下,如果超类没有无参数构造函数,编译器将会抱怨,因此您必须验证它是否存在。如果你的类没有显式的超类,那么它有一个隐式的超类Object,它有一个无参数的构造函数。
顺便说一句,在它的构造函数中启动一个线程并不是一个好习惯。执行此操作时可能会发生一些线程争用情况。在致电a.start()
后致电new A()
会好得多。此外,定义一个实现Runnable
而不是扩展Thread
的类是一种更好的模式。所以你的代码应该是:
class A implements Runnable() {
public A() {
// don't start it here
}
public void run() {
...
}
}
...
Thread a = new Thread(new A());
a.start();
Thread b = new Thread(new B());
b.start();
答案 3 :(得分:2)
A
扩展Thread
,B
扩展A
,因此当您创建A
的实例和B
的实例时,已经创建了Thread
的两个实例。
请注意,通常首选不来扩展Thread
,而是只实现Runnable
- 然后传递Runnable
到Thread(Runnable)
构造函数。从设计的角度来看,这最终变得更加清晰 - 你并没有真正尝试改变线程行为,你只是给它一个不同的任务来执行。
(通常最好使用java.util.concurrent中的工具而不是直接创建线程,但我们去......)
答案 4 :(得分:1)
正在创建2个线程,因为您通过运行以下行来要求它:
A a = new A();
B b = new B();