This 引述逃逸
This 引用逃逸
在Java 并发编程书里有个例子程序清单3-7 谈到 this escape。 开始没有想明白, 仔细琢磨了些时间发现代码主要的问题是在建构函数中创建了一个匿名类,然后发布了这个匿名类。
import java.util.*; public class ThisEscape { private final int num; public ThisEscape(EventSource source) { source.registerListener( new EventListener() { public void onEvent(Event e) { doSomething(e); } }); num = 42; } private void doSomething(Event e) { if (num != 42) { System.out.println("Race condition detected"); } } }
这段代码如果被 编译,然后JD-GUI 反编译看到得 doSomething(e); 就会变成
ThisEscape.this.doSomething(e); 这个应该是 java inner class 调用外部class的标准方式 - 外部类名.this.方法名
如果进一步的深究, 我们知道 ThisEscape编译后会有两个class 文件。一个是 ThisEscape.class, 另个一个会是 ThisEscape$1.class 给这个匿名类。
它们的内容差不多是这个样子的
public class ThisEscape {
private final int num;
public ThisEscape(EventSource source) {
source.registerListener(new ThisEscape$1(this));
num = 42;
}
private void doSomething(Event e) {
if (num != 42)
System.out.println(
"Race condition detected ");
}
static void access$000(ThisEscape _this, Event event) {
_this.doSomething(event);
}
}
class ThisEscape$1 implements EventListener {
final ThisEscape this$0;
ThisEscape$1(ThisEscape thisescape) {
this$0 = thisescape;
super();
}
public void onEvent(Event e) {
ThisEscape.access$000(this$0, e);
}
}
这样如果 new ThisEscape$1(this) 在另外的线程中被执行的话, 就可能导致 逃逸出去的this 的 num 还没有 执行 num = 42; Race condition detected 会不时的显示在console 里面。
结论 1, 就是不要在 建构函数随便创建匿名类然后 发布它们。
2, 不用再建构函数中随便起线程, 如果起要看有没有发布匿名类对象。