假设我有一个实现 Runnable 接口的抽象基类。
public abstract class Base implements Runnable {
protected int param;
public Base(final int param) {
System.out.println("Base constructor");
this.param = param;
// I'm using this param here
new Thread(this).start();
System.out.println("Derivative thread created with param " + param);
}
@Override
abstract public void run();
}
这是几个衍生类之一。
public class Derivative extends Base {
public Derivative(final int param) {
super(param);
}
@Override
public void run() {
System.out.println("Derivative is running with param " + param);
}
public static void main(String[] args) {
Derivative thread = new Derivative(1);
}
}
重点是我希望我的基类做一些常规的事情,而不是每次都复制它。
实际上,它运行良好,输出始终相同:
基础构造函数
使用参数 1 创建的派生线程
导数正在使用参数 1 运行
但是在JAVA中启动一个调用构造函数中的抽象方法的线程安全吗?因为据我所知,在 C++ 和 C# 中,大多数情况下它是不安全的。
谢谢你!
这段代码演示了为什么你应该never从构造函数调用抽象方法或任何其他可重写的方法:
abstract class Super {
Super() {
doSubStuff();
}
abstract void doSubStuff();
}
class Sub extends Super {
String s = "Hello world";
void doSubStuff() {
System.out.println(s);
}
}
public static void main(String[] args) {
new Sub();
}
运行时,会打印null
。这意味着构造函数中唯一的“安全”方法是私有方法和/或最终方法。
另一方面,您的代码实际上并不从构造函数调用抽象方法。相反,您将未初始化的对象传递给另一个线程进行处理,这更糟糕,因为您正在启动的线程可能会被赋予优先级并在您的线程之前执行。Base
完成其初始化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)