this引用逸出

逸出:某个不应被发布的对象被发布
发布:使对象在作用域之外的代码中被使用。例如get()获得对象或者将new出的对象放到外部集合中。
《Java并发编程实战》3-2节中提到this隐式逸出,并给出了示例代码:

public class ThisEscape {
    public ThisEscape(EventSource source) {
        source.registerListener(new EventListener() {
            public void onEvent(Event e) {
                doSomething(e);
            }
        });
    }

    void doSomething(Event e) {
    }


    interface EventSource {
        void registerListener(EventListener e);
    }

    interface EventListener {
        void onEvent(Event e);
    }

    interface Event {
    }
}

这个例子会导致逸出是因为doSomething方法是ThisEscape的实例化对象的方法,在注册了监听器后即隐含了将ThisEscape实例化对象发布出去(在其他线程中,可以被EventSource的实例化对象使用),而此时,ThisEscape的构造函数并未执行完,未构造完成的对象被发布,有可能被监听器调用,这时可能会发生异常。比较浅显的例子如监听器调用触发onEvent调用doSomething时需使用ThisEscape实例对象的成员变量,而实例对象还未完成构造,成员变量还未分配空间。
书中给出的解决方法:

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;
    }

    void doSomething(Event e) {
    }


    interface EventSource {
        void registerListener(EventListener e);
    }

    interface EventListener {
        void onEvent(Event e);
    }

    interface Event {
    }
}

即将构造与使用(发布)分离,构造函数虽然实例化了监听器SafeListener,但并未进行注册,也就不会发布。同样的为了避免逸出,如果要在构造函数中启动一个新的线程,那么不能立即执行这个线程,而是在构造函数外,通过start方法启动。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值