第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

ThreadLocal 的使用

1. 前言

本節(jié)內(nèi)容主要是對(duì) ThreadLocal 進(jìn)行深入的講解,具體內(nèi)容點(diǎn)如下:

  • 了解 ThreadLocal 的誕生,以及總體概括,是學(xué)習(xí)本節(jié)知識(shí)的基礎(chǔ);
  • 了解 ThreadLocal 的作用,從整體層面理解 ThreadLocal 的程序作用,為本節(jié)的次重點(diǎn);
  • 掌握 ThreadLocal set 方法的使用,為本節(jié)重點(diǎn)內(nèi)容;
  • 掌握 ThreadLocal get 方法的使用,為本節(jié)重點(diǎn)內(nèi)容;
  • 掌握 ThreadLocal remove 方法的使用,為本節(jié)重點(diǎn)內(nèi)容;
  • 掌握多線程下的 ThreadLocal 的使用,為本節(jié)內(nèi)容的核心。

2. ThreadLocal 概述

誕生:早在 JDK 1.2 的版本中就提供 java.lang.ThreadLocal,ThreadLocal 為解決多線程程序的并發(fā)問題提供了一種新的思路。使用這個(gè)工具類可以很簡(jiǎn)潔地編寫出優(yōu)美的多線程程序。

概述:ThreadLocal 很容易讓人望文生義,想當(dāng)然地認(rèn)為是一個(gè) “本地線程”。其實(shí),ThreadLocal 并不是一個(gè) Thread,而是 Thread 的局部變量,也許把它命名為 ThreadLocalVariable 更容易讓人理解一些。

當(dāng)使用 ThreadLocal 維護(hù)變量時(shí),ThreadLocal 為每個(gè)使用該變量的線程提供獨(dú)立的變量副本,所以每一個(gè)線程都可以獨(dú)立地改變自己的副本,而不會(huì)影響其它線程所對(duì)應(yīng)的副本。

總體概括:從線程的角度看,目標(biāo)變量就象是線程的本地變量,這也是類名中 “Local” 所要表達(dá)的意思。

了解完 ThreadLocal 的總體介紹后,對(duì)其有了一個(gè)總體的了解,那我們接下來繼續(xù)探究 ThreadLocal 的真實(shí)面貌以及使用。

3. ThreadLocal 的作用

作用:ThreadLocal 是 JDK 包提供的,它提供了線程本地變量,也就是如果你創(chuàng)建了一個(gè) ThreadLocal 變量,那么訪問這個(gè)變量的每個(gè)線程都會(huì)有這個(gè)變量的一個(gè)本地副本。當(dāng)多個(gè)線程操作這個(gè)變量時(shí),實(shí)際操作的是自己本地內(nèi)存里面的變量,從而避免了線程安全問題。

圖片描述

ThreadLocal 是線程本地存儲(chǔ),在每個(gè)線程中都創(chuàng)建了一個(gè) ThreadLocalMap 對(duì)象,每個(gè)線程可以訪問自己內(nèi)部 ThreadLocalMap 對(duì)象內(nèi)的 value。通過這種方式,避免資源在多線程間共享。

使用場(chǎng)景:如為每個(gè)線程分配一個(gè) JDBC 連接 Connection。這樣就可以保證每個(gè)線程的都在各自的 Connection 上進(jìn)行數(shù)據(jù)庫的操作,不會(huì)出現(xiàn) A 線程關(guān)了 B 線程正在使用的 Connection。還有 Session 管理等問題。

4. ThreadLocal set 方法

方法介紹:set 方法是為了設(shè)置 ThreadLocal 變量,設(shè)置成功后,該變量只能夠被當(dāng)前線程訪問,其他線程不可直接訪問操作改變量。

實(shí)例

public class DemoTest{
    public static void main(String[] args){
        ThreadLocal<String> localVariable = new ThreadLocal<> () ;
        localVariable.set("Hello World");
    }
}

Tips:set 方法可以設(shè)置任何類型的值,無論是 String 類型 ,Integer 類型,Object 等類型,原因在于 set 方法的 JDK 源碼實(shí)現(xiàn)是基于泛型的實(shí)現(xiàn),此處只是拿 String 類型進(jìn)行的舉例。

實(shí)例

public void set(T value) { // T value , 泛型實(shí)現(xiàn),可以 set 任何對(duì)象類型
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

5. ThreadLocal get 方法

方法介紹:get 方法是為了獲取 ThreadLocal 變量的值,get 方法沒有任何入?yún)?,直接調(diào)用即可獲取。

實(shí)例

public class DemoTest{
    public static void main(String[] args){
        ThreadLocal<String> localVariable = new ThreadLocal<> () ;
        localVariable.set("Hello World");
        System.out.println(localVariable.get());
    }
}

結(jié)果驗(yàn)證

Hello World

探究:請(qǐng)看如下程序,并給出輸出結(jié)果

實(shí)例

public class DemoTest{
    public static void main(String[] args){
        ThreadLocal<String> localVariable = new ThreadLocal<> () ;
        localVariable.set("Hello World");
        localVariable.set("World is beautiful");
        System.out.println(localVariable.get());
        System.out.println(localVariable.get());
    }
}

探究解析:從程序中來看,我們進(jìn)行了兩次 set 方法的使用。

第一次 set 的值為 Hello World ;第二次 set 的值為 World is beautiful。接下來我們進(jìn)行了兩次打印輸出 get 方法,那么這兩次打印輸出的結(jié)果都會(huì)是 World is beautiful。 原因在于第二次 set 的值覆蓋了第一次 set 的值,所以只能 get 到 World is beautiful。

結(jié)果驗(yàn)證

World is beautiful
World is beautiful

總結(jié):ThreadLocal 中只能設(shè)置一個(gè)變量值,因?yàn)槎啻?set 變量的值會(huì)覆蓋前一次 set 的值,我們之前提出過,ThreadLocal 其實(shí)是使用 ThreadLocalMap 進(jìn)行的 value 存儲(chǔ),那么多次設(shè)置會(huì)覆蓋之前的 value,這是 get 方法無需入?yún)⒌脑?,因?yàn)橹挥幸粋€(gè)變量值。

6. ThreadLocal remove 方法

方法介紹:remove 方法是為了清除 ThreadLocal 變量,清除成功后,該 ThreadLocal 中沒有變量值。

實(shí)例

public class DemoTest{
    public static void main(String[] args){
        ThreadLocal<String> localVariable = new ThreadLocal<> () ;
        localVariable.set("Hello World");
        System.out.println(localVariable.get());
        localVariable.remove();
        System.out.println(localVariable.get());
    }
}

Tips:remove 方法同 get 方法一樣,是沒有任何入?yún)⒌模驗(yàn)?ThreadLocal 中只能存儲(chǔ)一個(gè)變量值,那么 remove 方法會(huì)直接清除這個(gè)變量值。

結(jié)果驗(yàn)證

Hello World
null

7. 多線程下的 ThreadLocal

對(duì) ThreadLocal 的常用方法我們已經(jīng)進(jìn)行了詳細(xì)的講解,那么多線程下的 ThreadLocal 才是它存在的真實(shí)意義,那么問了更好的學(xué)習(xí)多線程下的 ThreadLocal,我們來進(jìn)行場(chǎng)景的創(chuàng)建,通過場(chǎng)景進(jìn)行代碼實(shí)驗(yàn),更好的體會(huì)并掌握 ThreadLocal 的使用。

場(chǎng)景設(shè)計(jì)

  • 創(chuàng)建一個(gè)全局的靜態(tài) ThreadLocal 變量,存儲(chǔ) String 類型變量;
  • 創(chuàng)建兩個(gè)線程,分別為 threadOne 和 threadTwo;
  • threadOne 進(jìn)行 set 方法設(shè)置,設(shè)置完成后沉睡 5000 毫秒,蘇醒后進(jìn)行 get 方法打印;
  • threadTwo 進(jìn)行 set 方法設(shè)置,設(shè)置完成后直接 get 方法打印,打印完成后調(diào)用 remove 方法,并打印 remove 方法調(diào)用完畢語句;
  • 開啟線程 threadOne 和 threadTwo ;
  • 執(zhí)行程序,并觀察打印結(jié)果。

結(jié)果預(yù)期:在 threadOne 設(shè)置成功后進(jìn)入了 5000 毫秒的休眠狀態(tài),此時(shí)由于只有 threadTwo 調(diào)用了 remove 方法,不會(huì)影響 threadOne 的 get 方法打印,這體現(xiàn)了 ThreadLocal 變量的最顯著特性,線程私有操作。

實(shí)例

public class DemoTest{
    static ThreadLocal<String> local = new ThreadLocal<>();
    public static void main(String[] args){

        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                local.set("threadOne's local value");
                try {
                    Thread.sleep(5000); //沉睡5000 毫秒,確保 threadTwo 執(zhí)行 remove 完成
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(local.get());
            }
        });
        Thread threadTwo = new Thread(new Runnable() {
            @Override
            public void run() {
                local.set("threadTwo's local value");
                System.out.println(local.get());
                local.remove();
                System.out.println("local 變量執(zhí)行 remove 操作完畢。");
            }
        });
        threadTwo. start();
        threadOne. start();
    }
}

結(jié)果驗(yàn)證

threadTwo's local value
local 變量執(zhí)行 remove 操作完畢。
threadOne's local value

從以上結(jié)果來看,在 threadTwo 執(zhí)行完 remove 方法后,threadOne 仍然能夠成功打印,這更加證明了 ThreadLocal 的專屬特性,線程獨(dú)有數(shù)據(jù),其他線程不可侵犯。

8. 小結(jié)

ThreadLocal 是解決線程安全問題一個(gè)很好的思路,它通過為每個(gè)線程提供一個(gè)獨(dú)立的變量副本解決了變量并發(fā)訪問的沖突問題。在很多情況下,ThreadLocal 比直接使用 synchronized 同步機(jī)制解決線程安全問題更簡(jiǎn)單,更方便,且結(jié)果程序擁有更高的并發(fā)性。

本節(jié)的重中之重是掌握 ThreadLocal 的方法使用以及其特點(diǎn),核心內(nèi)容為多線程下的 ThreadLocal 的使用。