《Java 并发编程实践》3.2章里面的关于发布和逸出的部分,主要是构造过程中this引用的逸出。
public class ThisEscape {
public ThisEscape(EventSource source){
source.registerListener(
new EventListener(){
public void onEvent(Event e){
doSomething()e;
}
});
}
}
这段代码的问题是对象逸出。
当我们声明一个非静态内部类时,编译器会添加对外部类的一个隐式引用。即非静态的内部类会持有外部类的一个隐式引用。
当我们实例化ThisEscape对象时,会调用source的registerListener方法,这时便启动了一个线程,而且这个线程持有了通过注册的内部类持有了外部ThisEscape对象引用,但此时ThisEscape对象却没有实例化完成(还没有返回一个引用),所以我们说,此时造成了一个this引用逸出,即还没有完成的实例化ThisEscape对象的动作,却已经暴露了对象的引用。其他线程访问还没有构造好的对象,可能会造成意料不到的问题。
书中给了解决方法,使用工厂方法防止this引用在构造过程中逸出。
public class SafeListener {
private final EventListener listener;
private SafeListener(){
listener = new EventListener(){
public void onEvent(Event e){
doSomething(e);
}
}
}
public static SafeListener newInstance(EventSource source){
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}
不在构造方法中注册监听器,就不会创建持有外部引用的线程,this引用也就不会逸出。