我正在阅读 Java 并发实践,下面的例子就是来自其中。我的问题是
这个引用转义是什么意思?会出现什么问题呢? 。 this 引用如何从 doSomething(e) 中转义。
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
}
);
}
}
这是如何解决问题的
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;
}
}
Edit :
我尝试过下面的例子
public class Escape {
public Escape( Printer printer ){
printer.print(new Escaper(){
@Override
public void parentData(){
theCulprit1(Escape.this);
}
public String name = "shal";
@Override
public void theCulprit(){
System.out.println( this.name );
System.out.println( Escape.this.age );
}
});
canAccess();
}
public void canAccess(){
this.age = "25";
}
public String age = "62";
@SuppressWarnings("unused")
public static void main(String args[]){
Escape escape = new Escape(new Printer());
}
}
class Printer{
public void print(Escaper escaper){
escaper.theCulprit();
escaper.parentData();
}
}
class Escaper{
public void parentData(){
}
public void theCulprit(){
}
public void theCulprit1(Escape escape){
System.out.println(escape.age);
}
}
由于逃生物体构造不完整
该输出应
62
62
当我像这样改变我的代码时
public class Escape {
private final Escaper escaper;
private Escape( ){
escaper = new Escaper(){
@Override
public void parentData(){
theCulprit1(Escape.this);
}
public String name = "shal";
public void theCulprit(){
System.out.println( name );
System.out.println( age );
}
};
canAccess();
}
public void canAccess(){
age = "25";
}
public String age = "62";
public static Escape newInstance( Printer printer){
Escape escape = new Escape();
printer.print(escape.escaper);
return escape;
}
@SuppressWarnings("unused")
public static void main(String args[]){
Escape.newInstance(new Printer());
}
}
在这里,它输出shal
25
25
我对吗 ?
另外,是否有任何操作重新排序,因为在第一个示例中,年龄被初始化为 62。
即使在我的第二个示例中没有将 escaper 字段设为最终值,它也能工作!
在第一种形式中,事件侦听器对象注册到事件源在构造函数内,因此它在构造函数完成之前使自己(以及通过关联的“this”对象)可用于事件源。如果内部类对象逃逸,外部对象也会逃逸。
为什么这是个问题?一旦注册了事件监听器,事件源就可以随时调用其方法。想象一下事件源正在使用的线程开始调用事件侦听器方法。现在甚至可以在构造函数完成之前发生这种情况。
然而,由于可见性问题,这个问题比看起来更严重。即使您将注册作为构造函数执行的“最后一个操作”,仍然有可能看到部分构造的对象或处于无效状态的对象。如果没有正确的happens-before排序,根本就没有可见性保证。
声明它是最终的可以在订购之前发生(因此是第二种形式)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)