构造函数中的线程启动¶
ID: java/thread-start-in-constructor
Kind: problem
Security severity:
Severity: warning
Precision: medium
Tags:
- reliability
- correctness
- concurrency
Query suites:
- java-security-and-quality.qls
在构造函数中启动线程可能会导致意外结果。如果扩展了该类,则线程可能在子类构造函数完成初始化之前启动,这可能不是预期的。
建议¶
避免在构造函数中启动线程。通常,类的构造函数只构造线程对象,应该提供一个单独的 start
方法来启动由构造函数创建的线程对象。
示例¶
在以下示例中,由于 Test
构造函数隐式调用 Super
构造函数,因此在 Super
构造函数中创建的线程可能在 this.name
初始化之前启动。因此,程序可能会输出“hello ”,然后输出一个空字符串。
class Super {
public Super() {
new Thread() {
public void run() {
System.out.println(Super.this.toString());
}
}.start(); // BAD: The thread is started in the constructor of 'Super'.
}
public String toString() {
return "hello";
}
}
class Test extends Super {
private String name;
public Test(String nm) {
// The thread is started before
// this line is run
this.name = nm;
}
public String toString() {
return super.toString() + " " + name;
}
public static void main(String[] args) {
new Test("my friend");
}
}
在以下修改后的示例中,在 Super
构造函数中创建的线程不会在构造函数中启动;main
在 this.name
初始化之后启动线程。这会导致程序输出“hello my friend”。
class Super {
Thread thread;
public Super() {
thread = new Thread() {
public void run() {
System.out.println(Super.this.toString());
}
};
}
public void start() { // good
thread.start();
}
public String toString() {
return "hello";
}
}
class Test extends Super {
private String name;
public Test(String nm) {
this.name = nm;
}
public String toString() {
return super.toString() + " " + name;
}
public static void main(String[] args) {
Test t = new Test("my friend");
t.start();
}
}
参考文献¶
IBM developerWorks: 不要在构造函数中启动线程。