java併發編程實戰------閱讀筆記第三章

一、不要在構造過程當中使this引用逸出。當且僅當對象的構造函數返回時,對象才處於可預測和一致的狀態,當從對象的構造函數中發佈對象時,只是發佈了一個還沒有構造完成的對象。只有當構造函數返回時,this引用才應該從線程中逸出,構造函數能夠將this引用保存到某個地方,只要其餘線程不會在構造函數以前使用它。若是想在構造函數中註冊事件監聽器或者啓動線程,能夠使用一個私有的構造函數和公共的工廠方法。緩存

public class SafeListener {
	
	private final EventListener listener;
	
	private SafeListener(){
		listener = new EventListener(){
			public void onEvent(Event e){
				//TODO
			}
		};
	}
	
	public static SafeListener newInstance(EventSource source){
		SafeListener safe = new SafeListener();
		source.registerListener(safe.listener);
		return safe;
	}
}

二、線程封閉(Thread Confinement),JDBC中的Connection對象就使用了線程封閉技術。JDBC規範並不要求Connection是線程安全的,可是鏈接池將其分配給一個線程以後,到Connection返回給鏈接池以前,鏈接池不會再把該Connection分配給其餘線程使用,所以至關於線程封閉了;ThreadLocal也是線程封閉的。 AD HOC線程封閉,不多用(未懂是什麼)。 棧封閉:只能經過局部變量才能訪問對象(局部變量被封閉在執行線程中,所以天然的封閉了)。書中的例子:安全

public int loadTheArk(Collection<Animal> candidates){
		
		SortedSet<Animal> animals;
		int numPairs = 0;
		Animal candidate = 0;
		
		//animals封閉在方法中,不要使其逸出
		animals = new TreeSet<Animal>(new SpecialGenderComparator());
		animals.addAll(candidates);
		for(Animal a : animals){
			if(candidate == null || !candidate.isPotentialMate(a))
				candidate = a;
			else{
				ark.load(new AnimalPair(candidate,a));
				++numPairs;
				candidate = null;
			}
		}
		return numPairs;
	}

線程封閉性更規範的方法:ThreadLocal,防止可變的單實例變量(Singleton)或全局變量進行共享。框架

private static ThreadLocal<Connection> connectionHolder 
		= new ThreadLocal<Connection>(){
			public Connection initialValue(){
				Connection conn = null;
				try {
					conn = DriverManager.getConnection("URL");
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return conn;
			}
	};
	
	public static Connection getConnection(){
		return connectionHolder.get();
	}

能夠用來保存事務上下文,避免調用每一個方法時都要傳遞執行上下文信息。這樣也會使運用了該機制的框架代碼與通常代碼耦合在一塊兒。濫用ThreadLocal相似於全局變量,下降代碼可重用性,並在類之間引入隱含的耦合性。函數

三、不變性:不可變對象必定是線程安全的,全部的域都是final類型的,對象也未必是不可變的,由於final類型的域能夠保存可變對象的引用。符合如下條件則不可變: .)對象建立之後其狀態就不能修改; .)對象的全部域都是final類型; .)對象都是正確建立的(在對象建立期間,this引用沒有逸出)。 「不可變的對象」與「不可變的對象引用」之間存在差別,保存在不可變對象中的程序狀態依然能夠更新,可經過一個保存新狀態的實例來替換原有的不可變對象。 大神們說的良好變成習慣:除非須要更高的可見性,不然將全部的域都聲明爲私有域;除非須要某個域是可變的,不然應將其聲明爲final域。 能夠使用指向不可變容器對象的volatile類型引用以緩存最新的結果。this

4安全發佈:安全發佈一個對象,對象引用和對象狀態必須同時對其餘線程可見,一個正確構造的對象能夠經過如下方式安全發佈: .)在靜態初始化函數中初始化一個對象引用; .)將對象的引用保存到volatile類型的域或者AtomicReferance對象中; .)將對象的引用保存到某個正確構造對象的final類型域中。 .)將對象的引用保存到一個由鎖保護的域中。線程

相關文章
相關標籤/搜索