在java并发编程实践-this溢出1中我们已经介绍this溢出的一种情形和解决方案,下面,我们再来还原一下《java并发编程实践》一书中,关于“在构造函数中发布内部类导致this溢出情形以及在构造函数中开启线程的情形”,虽然,该书中已经给出了解决该问题的方案,但是,没有给出具体的出现错误的示例,下面,以一个在构造函数中开启线程的示例来进行说明:
ThisEscapeInner类
public class ThisEscapeInner {
public ThisEscapeInner() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// 调用ThisEscapeInner类中的方法,内部类具有对外部类this的应用
Say();
}
});
// 此时开启线程,可能在调用Say()时会导致不可预见性的结果
thread.start();
}
public void Say() {
System.out.println("ThisEscapeInner.Say()");
}
public static void main(String[] args) {
new ThisEscapeSon1();
}
}
ThisEscapeSon1类
class ThisEscapeSon1 extends ThisEscapeInner {
private final String name;
public ThisEscapeSon1() {
this.name = "Hello Word";
System.out.println("ThisEscapeSon1");
}
public ThisEscapeSon1(String name) {
this.name = name;
System.out.println("ThisEscapeSon1");
}
/*
* 在子类中重写Say方法
*/
public void Say() {
System.out.println("ThisEscapeSon1.Say()-->" + name);
}
}
运行结果:可能会打印:ThisEscapeSon1.Say()-->null
,也可能会打印ThisEscapeSon1.Say()-->HelloWorld
,运行结果具有不确定性,其原因是,start()的线程的执行时序并不是确定的,不知道它是否this.name = "Hello Word";
语句执行之前还是之后调度执行。
解决方法:除了使用java并发编程实践-this溢出1上介绍的方法来处理Say()
方法,同时,按照《java并发编程实践》中的建议不要在构造函数中开启线程。