跟著執行個體學習java多線程6-如何正確發布安全執行緒的對象,java6-

來源:互聯網
上載者:User

跟著執行個體學習java多線程6-如何正確發布安全執行緒的對象,java6-


我們前面所講的一切其實都只是為了一個目標那就是能正確發布一個安全執行緒的對象。

一:線程封閉

這個很好理解如果一個變數是在一個線程中完成的狀態改變,那麼這個變數肯定是安全執行緒的。

我們常使用的是棧封閉和ThreadLocal類。

在java運行時記憶體區中有一個虛擬機器棧,棧封閉說的就是這個棧,這個棧是線程私人的,它的生命週期與線程相同。虛擬機器棧描述描述的是java方法執行的記憶體模型:每個方法被執行的時候會同時建立一個棧幀用於儲存局部變數、運算元棧等。每一個方法被調用直至執行完成的過程,就對應著一個棧幀在虛擬機器棧中的從入棧到出棧的過程。

那麼我們定義在被呼叫者法的內部的局部變數就被封閉在棧中了,這樣的變數只要不將該變數的引用發布出去那麼它一定是安全執行緒的。

public int getBadNum(List<String> paralist){List<String> localList;int num = 0;localList = paralist;for(String t:localList){if("bad".equals(t)){++num;}}return num;}

該方法中num無論如何都不會破壞棧的封閉性,我們也看到localList是一個局部對象,一個對象的引用指向了它,而它被封閉線上程中所以那個引用也會被封閉線上程中執行完成。但是如何一旦把localList對象發布出去那麼封閉性將被破壞。其它外部方法會怎麼使用它我們就不能確定了。

ThreadLocal變數我們在代碼中很少使用了,因為它的特性會降低代碼的可重用性,並在類之間引入隱含的耦合性,因此在使用時要格外小心,我們這裡就不講它的執行個體了。

二:不可變對象

不可變對象有以下幾個條件。

       對象建立以後其狀態就不能修改。

       對象的所有域都是final的類型。

       對象是正確建立的。

事實上我們經常會使用這樣的不可變對象在程式啟動時對其進行初始化,然後多線程並發訪問,這裡最關鍵的是正確建立對象並初始化,所以一定是保證所有的對象不能發生逸出,通常的做法是在所有這樣的變數初始化完成在啟動並發訪問線程,這一點一定要保證。

三:安全發布常用模式

      1: 在靜態初始化函數中初始化一個對象的引用。

      

public class MongoDBTools {protected Logger logger = LoggerFactory.getLogger(MongoDBTools.class);private MongoClient configClient;private DB configDB;private Map<String, MongoTemplate> shardMongoTemplateMap = new HashMap<String, MongoTemplate>();private MongoDBTools() {init();}private static class SingletionHolder {private static MongoDBTools appConfigTools = new MongoDBTools();}public static MongoDBTools getInstance() {return SingletionHolder.appConfigTools;}@SuppressWarnings("deprecation")public void init() {}}


我們使用getInstance方法獲得的就是利用static域初始化好的單例對象。

        2: 將對象的引用儲存到volatile類型的域或是AtomicReferance對象中。

這種方式有很大的局限性,一般只適用於唯讀共用模式。

        3:將對象的引用儲存到某個正確構造的對象的final類型域中。

這是方式我們經常會用但是如果是可變狀態的對象的發布就一定要通過鎖來處理了。

package com.uskytec.ubc.interf.webservice;import java.util.concurrent.ConcurrentHashMap;/** * @author gaoxu * */public class ConcurrentHashMapInstance {static ConcurrentHashMap<?, ?>  chm = null;/**擷取ConcurrentHashMap的全域對象 * @return */public synchronized static ConcurrentHashMap<?, ?> getCHM(){if(chm==null){chm = new ConcurrentHashMap<String, Boolean>();}return chm;}}


利用java提供的ConcurrentHashMap並發對象可以實現安全執行緒共用。
      4:將對象的引用儲存到一個由鎖保護的域中。

package com.uskytec.ubc.foundation.queue;import java.util.HashMap;/**路由cache * @author GaoXu * */public class RouteCache {private static RouteCache instance = null;public synchronized static RouteCache getInstance(){if (instance == null)instance = new RouteCache();return instance;}private final static HashMap<String,Object> routeCache = new HashMap<String,Object>();/** * @param key * @param value * @return */public synchronized int add(String key,Object value){routeCache.put(key, value);return 1;}/** * @param key * @return */public synchronized Object get(String key){    if (routeCache != null)    return routeCache.get(key);    return null;}}執行個體中的routeCache是一個可變狀態的對象,所以我們採用安全執行緒共用的方式發布出來,針對它的操作一律採用公有介面提供操作。

掌握好這些發布策略我們就能更好的編寫安全執行緒共用對象,同時也可以安全的實現並發任務的執行。





相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.