天天看点

Java并发编程实践笔记之—发布和逸出(Publication and Escape)

什么是发布对象——使对象在当前作用域之外的代码中使用

什么是逸出——当某个不应该发布的对象被发布时

对象如何逸出的

  • 最简单的方法是将对象的引用保存到一个公有的静态变量中
  • 当发布某个对象时,可能会间接地发布其他对象。如果将一个对象添加到被发布的集合对象中,那么同样会发布这个对象
  • 当发布一个对象时,在该对象的非私有域中引用的所有对象同样会被发布;或者说当把一个对象传递给某个外部方法时,就相当于发布了这个对象
  • 不安全的对象构造过程:指this引用在构造函数中逸出
    1. 常见的错误做法1是,在构造函数中启动一个线程,this引用就被新创建的线程共享了
    2. 常见的错误做法2是,在构造函数中注册一个事件监听器,this引用就被触发被监听事件的线程共享了
    3. 解决办法是:使用一个私有的构造函数和一个公共的工厂方法,看下面的例子
      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) {
             //只有当构造函数返回时,this引用才应该从线程中逸出
             SafeListener safe = new SafeListener();
              source.registerListener(safe.listener);
              return safe;
          }
      }
                 

注意:只有当对象的构造函数返回时,对象才处于可预测和一致的状态。因此,当从对象的构造函数中发布对象时,只是发布了一个尚未构造完成的对象,即使发布对象的语句在最后一行也是如此,如果this在构造过程中逸出,那么这种对象就被认为是不正确的构造