91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中怎么實現線程封閉

發布時間:2021-07-01 15:26:12 來源:億速云 閱讀:179 作者:Leah 欄目:大數據

Java中怎么實現線程封閉,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

什么是線程封閉

當訪問共享變量時,往往需要加鎖來保證數據同步。一種避免使用同步的方式就是不共享數據。如果僅在單線程中訪問數據,就不需要同步了。這種技術稱為線程封閉。在Java語言中,提供了一些類庫和機制來維護線程的封閉性,例如局部變量和ThreadLocal類,本文主要深入講解如何使用ThreadLocal類來保證線程封閉。

理解ThreadLocal類

ThreadLocal類能使線程中的某個值與保存值的對象關聯起來,它提供了get、set方法,這些方法為每個使用該變量的線程保存一份獨立的副本,因此get總是set當前線程的set最新值。

首先我們來看個例子,這個例子來自于http://www.cnblogs.com/dolphin0520/p/3920407.html

public class Test1 {

    ThreadLocal<Long> longLocal = new ThreadLocal<Long>();
    ThreadLocal<String> stringLocal = new ThreadLocal<String>();

    public void set() {
        longLocal.set(Thread.currentThread().getId());
        stringLocal.set(Thread.currentThread().getName());
    }

    public long getLong() {
        return longLocal.get();
    }

    public String getString() {
        return stringLocal.get();
    }
    public static void main(String[] args) throws InterruptedException {
        final Test1 test = new Test1();

        test.set();
        System.out.println(test.getLong());
        System.out.println(test.getString());

        Thread thread1 = new Thread(() -> {
            test.set();
            System.out.println(test.getLong());
            System.out.println(test.getString());
        });
        thread1.start();
        thread1.join();

        System.out.println(test.getLong());
        System.out.println(test.getString());
    }
}

運行該程序,代碼輸出的結果為:

1

main

10

Thread-0

1

main

從這段代碼可以看出在mian線程和thread1線程確實都保存著各自的副本,它們的副本各自不干擾。

ThreadLocal源碼解析

來從源碼的角度來解析ThreadLocal這個類,這個類存放在java.lang包,這個類有很多方法。

Java中怎么實現線程封閉

它內部又個ThreadLocalMap類,主要有set()、get()、setInitialValue 等方法。

首先來看下set方法,獲取當前Thread的 map,如果不存在則新建一個并設置值,如果存在設置值,源碼如下:

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

跟蹤createMap,可以發現它根據Thread創建來一個ThreadLocalMap。

  void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

t.threadLocals為當前線程的一個變量,也就是ThreadLocal的數據都是存放在當前線程的threadLocals變量里面的,由此可見用ThreadLocal存放的數據是線程安全的。因為它對于不同的線程來,使用ThreadLocal的set方法都會根據線程判斷該線程是否存在它的threadLocals成員變量,如果沒有就建一個,有的話就存下數據。

ThreadLocal.ThreadLocalMap threadLocals = null;

ThreadLocalMap為ThreadLocal的一個內部類,源碼如下:

 static class ThreadLocalMap {

        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }

可以看到ThreadLocalMap的Entry繼承了WeakReference,并且使用ThreadLocal作為鍵值。

在使用ThreadLocal的get方法之前一定要先set,要不然會報空指針異常。還有一種方式就是在初始化的時候調用initialValue()方法賦值。改造下之前的例子,代碼如下:

public class Test2 {

    ThreadLocal<Long> longLocal = new ThreadLocal<Long>(){

        @Override
        protected Long initialValue() {
            return Thread.currentThread().getId();
        }
    };
    ThreadLocal<String> stringLocal = new ThreadLocal<String>(){
        @Override
        protected String initialValue() {
            return Thread.currentThread().getName();
        }
    };

    public long getLong() {
        return longLocal.get();
    }

    public String getString() {
        return stringLocal.get();
    }

    public static void main(String[] args) throws InterruptedException {
        final Test2 test = new Test2();

        System.out.println(test.getLong());
        System.out.println(test.getString());

        Thread thread1 = new Thread(() -> {

            System.out.println(test.getLong());
            System.out.println(test.getString());
        });
        thread1.start();
        thread1.join();

        System.out.println(test.getLong());
        System.out.println(test.getString());
    }
}

運行該程序,代碼輸出的結果為:

1

main

10

Thread-0

1

main

ThreadLocal常用的使用場景

通常講JDBC連接保存在ThreadLocal對象中,每個對象都有屬于自己的連接,代碼如下:

private static ThreadLocal<Connection> connectionHolder
= new ThreadLocal<Connection>() {
    public Connection initialValue() {
       return DriverManager.getConnection(DB_URL);
    }
};

public static Connection getConnection() {
    return connectionHolder.get();
}

關于Java中怎么實現線程封閉問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

盐城市| 潜江市| 南木林县| 五峰| 阜宁县| 白水县| 改则县| 远安县| 枞阳县| 清水河县| 敦煌市| 万盛区| 霍林郭勒市| 陇南市| 阿城市| 鹤山市| 蒙城县| 亳州市| 诸城市| 岳池县| 日土县| 黄平县| 古浪县| 施秉县| 岐山县| 高州市| 临沭县| 双城市| 麦盖提县| 大厂| 赤壁市| 伊川县| 商都县| 三台县| 同江市| 嘉黎县| 高唐县| 蒙自县| 稷山县| 邻水| 扶余县|