java - 引用封闭对象通过匿名类转义-java

标签 java concurrency reference this anonymous-class

我正在阅读 Java concurrency in practice,以下示例来自该书。我的问题是 这个引用转义是什么意思?会有什么问题? . 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;
    }
}

编辑:

我试过下面的例子

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 字段设置为 final,它也能正常工作!

最佳答案

在第一种形式中,事件监听器对象在构造函数中注册到事件源,因此它使自己(并通过关联“this”对象)在事件源之前可用构造函数完成。如果内部类对象逃逸,则外部对象也会逃逸。

为什么这是个问题?一旦注册了事件监听器,事件源就可以随时调用它的方法。想象一下事件源正在使用的线程开始调用事件监听器方法。这现在甚至可以在构造函数完成之前发生。

但是,由于可见性问题,这个问题比看起来更糟。即使您将注册作为构造函数执行的“最后一个操作”,仍然有可能看到部分构造对象或处于无效状态的对象。如果没有适当的 happens-before ordering,根本就没有可见性保证。

将它声明为 final 提供在订购之前发生的事情(因此是第二种形式)。

关于java - 引用封闭对象通过匿名类转义-java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5129592/

相关文章:

java - 如何使用 HTML 和 CSS 为我的 Java 应用程序创建用户界面?

java - 遍历一个对象并从它的所有变量中获取值

c++ - 对象的代理,适当的 const 限定和缺乏

java - 使用静态对象的第二个非静态引用时出现 NullPointer 异常

java - 在java中编写JPEG时如何禁用压缩?

java - putIfAbsent 方法是否阻塞?

concurrency - 并行流

java - 同一逻辑的响应时间在不同的并发请求下快速增长

c++ - 将引用绑定(bind)到 C++ 中尚未构造的对象是否安全?

java - 针对测试 MCC 帐户(创建帐户)进行测试时出现 AuthorizationError.USER_PERMISSION_DENIED