標籤:span collect potential logs else closed 全域 分享 避免
線程封閉:當訪問共用的可變資料時,通常需要同步。一種避免同步的方式就是不共用資料。如果僅在單線程內訪問資料,就不需要同步,這種技術稱為線程封閉(thread confinement)
線程封閉技術一個常見的應用就是JDBC的Connection對象,JDBC規範並沒有要求Connection對象必須是安全執行緒的,在伺服器應用程式中,線程從串連池擷取一個Connection對象,使用完之後將對象返還給串連池。下面介紹幾種線程封閉技術:
1、Ad-hoc線程封閉
Ad-hoc線程封閉是指,維護線程的封閉性的職責完全由程式實現承擔,是非常脆弱的,因此在程式中盡量少使用,一般使用更強的線程封閉技術,比如棧封閉或者ThreadLocal類。
2、棧封閉
棧封閉是線程封閉的一種特列,在棧封閉中,只能通過局部變數才能訪問對象。局部變數的固有屬性之一就是封閉在執行棧中,其他線程無法訪問這個棧,棧封閉也稱為線程內部使用或者線程局部使用。簡單的說就是局部變數。多個線程訪問一個方法,此方法中的局部變數都會被拷貝一分兒到線程棧中。所以局部變數是不被多個線程所共用的,也就不會出現並發問題。所以能用局部變數就別用全域的變數,全域變數容易引起並發問題。
比如下面的例子:
1 public int loadTheArk(Collection<Animal> candidates) { 2 SortedSet<Animal> animals; 3 int numPairs = 0; 4 Animal candidate = null; 5 6 //animals被封裝在方法中,不要使它們溢出 7 animals = new TreeSet<Animal>(new SpeciesGenderComparator()); 8 animals.addAll(candidates); 9 for(Animal a:animals){ 10 if(candidate==null || !candidate.isPotentialMate(a)){ 11 candidate = a; 12 }else{ 13 ark.load(new AnimalPair(candidate,a)); 14 ++numPairs; 15 candidate = null; 16 } 17 } 18 return numPairs; 19 }View Code
在loadTheArk中執行個體化一個TreeSet對象,並將該對象的一個引用儲存到animals中。此時,只有一個引用指向集合animals,這個引用被封閉到局部變數中,因此也被封閉到局部變數中。然而,如果發布了對集合animals(或者該對象中的任何內部資料)的引用,那麼封閉性將被破壞,並導致對象animals的逸出。
3、ThreadLocal類
Java多線程——線程封閉