java併發編程實戰的解釋,不夠詳細,尤爲this引用逸出讓人理解有些費解,java併發編程實戰裏面的內容就直接拷貝過來java
發佈:使對象可以在當前做用域以外的代碼中使用 逸出:當某個不應被髮布的對象被髮布時,這種狀況稱爲逸出 發佈內部狀態將會破壞封裝性,並使得程序難以維持不變性條件 當某個對象逸出後,必須對程序進行分析,以便找出哪些對象或線程可能會誤用該對象,這正是使用封裝的最主要緣由:使對程序的正確性分析變爲可能,並使無心中破壞設計約束條件變得更難 不管其它的線程會對逸出的對象引用執行何種操做,都不重要,由於誤用該引用的風險始終是客觀存在的
代碼示例:編程
//只是代碼示例,不推薦這樣初始化List public class test { public List<Animal> animals = new ArrayList<Animal>(){{ add(new Animal()); }}; }
List對象和List中的Animal對象都被髮布出去。併發
代碼示例:函數
//只是代碼示例,不推薦這樣初始化List public class test { private List<Animal> animals = new ArrayList<Animal>(){{ add(new Animal()); }}; public List<Animal> getAnimals(){ return animals; } }
一、2的同樣,List對象和List中的Animal對象發佈出去。只是一個是方法發佈出去,一個是屬性發布出去。this
外部方法定義: 對當前類來講,外部方法是指行爲不徹底由當前類來規定的方法,包括其餘類中定義的方法以及當前類中能夠被改寫的方法(既不是私有方法,也不是final方法)
代碼示例:線程
public class test { public void setAnimals(Animal animal){ animal.setDag( new Dog(){ public void doSomething(){ ... }; } ) } }
當前類test來講,setDag爲外部方法,Dog就被髮布了。設計
基於外部方法發佈對象引出this引用逸出問題。直接拿java併發編程實戰的代碼code
public class ThisEscape { public ThisEscape(EventSource source){ source.registerListener( new EventListener(){ public void onEvent(Event e){ doSomething(e) } }); } } java併發編程實戰的解釋: 當ThisEscape發佈EventListener時,它也無條件地發佈了封裝(enclosing)ThisEscape的實例,由於內引類(inner class inst ances)的實例包含了對封裝實例隱含的引用。
這裏發佈new EventListener()內部對象,隱式的有個this。也就是ThisEscape也會被髮布出去,可是ThisEscape尚未構建完成,存在逸出的可能,ThisEscape在未構建完成被髮布了。怎麼處理這個可能逸出的問題,就是讓ThisEscape構建完成再發布出去就能夠了。java併發編程實戰的提到私有構造函數+公共的工廠方法解決可能逸出的問題。對象
public class ThisEscape { private final EventListener listener; private ThisEscape(){ listener = new EventListener(){ public void onEvent(Event e){ doSomething(e) } }; } public static ThisEscape newInstance(EventSource source){ ThisEscape thisEscape = new ThisEscape(); source.registerListener(thisEscape.listener); return thisEscape; } }
同理在構造函數能夠新建線程,當不要start()。start()的話this被新線程共享。下面代碼就是錯誤的:作用域
public class ThisEscape { private Thread thread; public ThisEscape(){ thread = new Thread(){ public void run(){ ... } }; thread.start(); //能夠在構造函數中new Thread 可是不要start } public static void main(String[] args){ ThisEscape a = new ThisEscape(); } }