成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Java中ThreadLocal是什么

Java中ThreadLocal是什么?這個問題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見到的。希望通過這個問題能讓你收獲頗深。下面是小編給大家?guī)淼膮⒖純?nèi)容,讓我們一起來看看吧!

創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比中方網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式中方網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋中方地區(qū)。費(fèi)用合理售后完善,十多年實體公司更值得信賴。

ThreadLocal基本在項目開發(fā)中基本不會用到, 但是面試官是比較喜歡問這類問題的;所以還是有必要了解一下該類的功能與原理的.

ThreadLocal是什么

ThreadLocal是一個將在多線程中為每一個線程創(chuàng)建單獨的變量副本的類; 當(dāng)使用ThreadLocal來維護(hù)變量時, ThreadLocal會為每個線程創(chuàng)建單獨的變量副本, 避免因多線程操作共享變量而導(dǎo)致的數(shù)據(jù)不一致的情況;

ThreadLocal類用在哪些場景

一般來說, ThreadLocal在實際工業(yè)生產(chǎn)中并不常見, 但是在很多框架中使用卻能夠解決一些框架問題; 比如Spring中的事務(wù)、Spring 中 作用域 ScopeRequest的Bean 使用ThreadLocal來解決.

ThreadLocal使用方法

1、將需要被多線程訪問的屬性使用ThreadLocal變量來定義; 下面以網(wǎng)上多數(shù)舉例的DBConnectionFactory類為例來舉例

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBConnectionFactory {

    private static final ThreadLocal<Connection> dbConnectionLocal = new ThreadLocal<Connection>() {
        @Override
        protected Connection initialValue() {
            try {
                return DriverManager.getConnection("", "", "");
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    };

    public Connection getConnection() {
        return dbConnectionLocal.get();
    }
}

這樣在Client獲取Connection的時候, 每個線程獲取到的Connection都是該線程獨有的, 做到Connection的線程隔離; 所以并不存在線程安全問題

ThreadLocal如何實現(xiàn)線程隔離

1、主要是用到了Thread對象中的一個ThreadLocalMap類型的變量threadLocals, 負(fù)責(zé)存儲當(dāng)前線程的關(guān)于Connection的對象, 以dbConnectionLocal 這個變量為Key, 以新建的Connection對象為Value; 這樣的話, 線程第一次讀取的時候如果不存在就會調(diào)用ThreadLocal的initialValue方法創(chuàng)建一個Connection對象并且返回;

具體關(guān)于為線程分配變量副本的代碼如下:

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

1、首先獲取當(dāng)前線程對象t, 然后從線程t中獲取到ThreadLocalMap的成員屬性threadLocals

2、如果當(dāng)前線程的threadLocals已經(jīng)初始化(即不為null) 并且存在以當(dāng)前ThreadLocal對象為Key的值, 則直接返回當(dāng)前線程要獲取的對象(本例中為Connection);

3、如果當(dāng)前線程的threadLocals已經(jīng)初始化(即不為null)但是不存在以當(dāng)前ThreadLocal對象為Key的的對象, 那么重新創(chuàng)建一個Connection對象, 并且添加到當(dāng)前線程的threadLocals Map中,并返回

4、如果當(dāng)前線程的threadLocals屬性還沒有被初始化, 則重新創(chuàng)建一個ThreadLocalMap對象, 并且創(chuàng)建一個Connection對象并添加到ThreadLocalMap對象中并返回。

如果存在則直接返回很好理解, 那么對于如何初始化的代碼又是怎樣的呢?

private T setInitialValue() {
    T value = initialValue();
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
    return value;
}

1、首先調(diào)用我們上面寫的重載過后的initialValue方法, 產(chǎn)生一個Connection對象

2、繼續(xù)查看當(dāng)前線程的threadLocals是不是空的, 如果ThreadLocalMap已被初始化, 那么直接將產(chǎn)生的對象添加到ThreadLocalMap中, 如果沒有初始化, 則創(chuàng)建并添加對象到其中;

同時, ThreadLocal還提供了直接操作Thread對象中的threadLocals的方法

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

這樣我們也可以不實現(xiàn)initialValue, 將初始化工作放到DBConnectionFactory的getConnection方法中:

public Connection getConnection() {
    Connection connection = dbConnectionLocal.get();
    if (connection == null) {
        try {
            connection = DriverManager.getConnection("", "", "");
            dbConnectionLocal.set(connection);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    return connection;
}

那么我們看過代碼之后就很清晰的知道了為什么ThreadLocal能夠?qū)崿F(xiàn)變量的多線程隔離了; 其實就是用了Map的數(shù)據(jù)結(jié)構(gòu)給當(dāng)前線程緩存了, 要使用的時候就從本線程的threadLocals對象中獲取就可以了, key就是當(dāng)前線程;

當(dāng)然了在當(dāng)前線程下獲取當(dāng)前線程里面的Map里面的對象并操作肯定沒有線程并發(fā)問題了, 當(dāng)然能做到變量的線程間隔離了;

現(xiàn)在我們知道了ThreadLocal到底是什么了, 又知道了如何使用ThreadLocal以及其基本實現(xiàn)原理了是不是就可以結(jié)束了呢? 其實還有一個問題就是ThreadLocalMap是個什么對象, 為什么要用這個對象呢?

ThreadLocalMap對象是什么

本質(zhì)上來講, 它就是一個Map, 但是這個ThreadLocalMap與我們平時見到的Map有點不一樣

1、它沒有實現(xiàn)Map接口;

2、它沒有public的方法, 最多有一個default的構(gòu)造方法, 因為這個ThreadLocalMap的方法僅僅在ThreadLocal類中調(diào)用, 屬于靜態(tài)內(nèi)部類

3、ThreadLocalMap的Entry實現(xiàn)繼承了WeakReference<ThreadLocal<?>>

4、該方法僅僅用了一個Entry數(shù)組來存儲Key, Value; Entry并不是鏈表形式, 而是每個bucket里面僅僅放一個Entry;

感謝各位的閱讀!看完上述內(nèi)容,你們對Java中ThreadLocal是什么大概了解了嗎?希望文章內(nèi)容對大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

分享名稱:Java中ThreadLocal是什么
當(dāng)前鏈接:http://jinyejixie.com/article18/pgesgp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、關(guān)鍵詞優(yōu)化、品牌網(wǎng)站制作品牌網(wǎng)站設(shè)計、定制開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
石阡县| 溧阳市| 大宁县| 平乡县| 墨玉县| 西充县| 焦作市| 龙胜| 桂阳县| 通城县| 泾川县| 玉环县| 贞丰县| 罗城| 嵊泗县| 崇仁县| 防城港市| 大洼县| 临湘市| 邛崃市| 报价| 新昌县| 泗水县| 文登市| 仪征市| 舟山市| 屏东市| SHOW| 横山县| 青海省| 崇左市| 武汉市| 长岭县| 泰兴市| 若尔盖县| 梁平县| 永泰县| 勐海县| 石门县| 改则县| 泰和县|