天天看點

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在構造過程中逸出,那麼這種對象就被認為是不正确的構造