JAVA併發編程筆記(3)

Publication and Escape

發佈一個對象意味着能夠從它能夠從它當前範圍之外被訪問到。比如,保存可以被其他代碼找到的這個對象的一個引用,或者將其作爲一個非私有方法的返回值,或者將其作爲參數傳遞給其它的類。

public static Set<Secret> knownSecrets;

public void initialize() {
knownSecrets = new HashSet<Secret>();
}

這個knownSecrets就被髮布了,並且,knownSecrets裏面添加的所有secret也都被髮布出去了。

class UnsafeStates {
private String[] states = new String[] {
"AK", "AL" ...
};
public String[] getStates() { return states; }
}

這個states就被髮布了,而且帶來的問題是任何調用者都能夠修改裏面的內容,這樣,很不安全。

public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
看明白這個ThisEscape爲什麼被髮布了麼?因爲它發佈了EventListener,而內部類會帶有一個隱式的對外部類的引用。

另外,上面這個類的一個嚴重問題是,在構造方法中this引用escape了。這也就意味着這個對象在被髮布的時候還處於一個不完整的狀態。一個常見的情形就是在類的構造方法中啓動一個線程。When an object creates a thread from its constructor, it almost always shares its this reference with the new thread, either explicitly (by passing it to the constructor) or implicitly (because the Thread or Runnable is an inner class of the owning object). 當然這本身沒什麼問題,但最好不要在構造方法中就啓動這個線程,而是把Thread.start()放到一個單獨的init方法中供其它對象調用。

要避免不完全構造的問題,可以採用下面的方式:

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;
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章