Java併發程式設計實戰--this引用逸出

衣舞晨風發表於2017-06-04

     最近在看《Java 併發程式設計實踐》看到3.2章裡面的關於釋出和逸出的部分,寫一下心得,算是mark一下,主要是構造過程中this引用的逸出。

     書上面給出了一個構造過程中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 {
  }
}

     這將導致this逸出,所謂逸出,就是在不該釋出的時候釋出了一個引用。在這個例子裡面,當我們例項化ThisEscape物件時,會呼叫source的registerListener方法,這時便啟動了一個執行緒,而且這個執行緒持有了ThisEscape物件(呼叫了物件的doSomething方法),但此時ThisEscape物件卻沒有例項化完成(還沒有返回一個引用),所以我們說,此時造成了一個this引用逸出,即還沒有完成的例項化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物件(通過構造器構造)之後,我們才啟動了監聽執行緒,也就確保了SafeListener物件是構造完成之後再使用的SafeListener物件。

     對於這樣的技術,書裡面也有這樣的註釋:

     具體來說,只有當建構函式返回時,this引用才應該從執行緒中逸出。建構函式可以將this引用儲存到某個地方,只要其他執行緒不會在建構函式完成之前使用它。

原文地址:
http://www.cnblogs.com/whatisjava/archive/2013/05/29/3106336.html

Java併發程式設計實戰pdf及案例原始碼下載:
http://download.csdn.net/detail/xunzaosiyecao/9851028

作者:jiankunking 出處:http://blog.csdn.net/jiankunking

相關文章