色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

ThreadLocal的定義、用法及優點

科技綠洲 ? 來源:Java技術指北 ? 作者:Java技術指北 ? 2023-09-30 10:14 ? 次閱讀

ThreadLocal

簡介

ThreadLocal是Java中一個非常重要的線程技術。它可以讓每個線程都擁有自己的變量副本,避免了線程間的競爭和數據泄露問題。在本文中,我們將詳細介紹ThreadLocal的定義、用法及其優點。

ThreadLocal是Java中一個用來實現線程封閉技術的類。它提供了一個本地線程變量,可以在多線程環境下使每個線程都擁有自己的變量副本。每個線程都可以獨立地改變自己的副本,而不會影響到其他線程的副本。ThreadLocal的實現是基于ThreadLocalMap的,每個ThreadLocal對象 都對應一個ThreadLocalMap,其中存儲了線程本地變量的值。

優缺點

ThreadLocal的主要優點是可以提高并發程序的性能和安全性,同時也存在一些缺點和使用場景需要注意。

優點:

  1. 提高并發性能:使用ThreadLocal可以避免多個線程之間的競爭,從而提高程序的并發性能。
  2. 保證線程安全:每個線程有自己獨立的變量副本,避免了線程安全問題。
  3. 簡化代碼:使用ThreadLocal可以避免傳遞參數的繁瑣,簡化代碼。

缺點:

  1. 內存泄漏:ThreadLocal變量副本的生命周期與線程的生命周期一樣長,如果線程長時間存在,而ThreadLocal變量沒有及時清理,就會造成內存泄漏。
  2. 增加資源開銷:每個線程都要創建一個獨立的變量副本,如果線程數很多,就會增加資源開銷。
  3. 不適用于共享變量:ThreadLocal適用于每個線程有獨立的變量副本的場景,不適用于共享變量的場景。

適用場景

  1. 線程安全的對象:ThreadLocal適用于需要在多個線程中使用的線程安全對象,例如SimpleDateFormat、Random等。
  2. 跨層傳遞參數:ThreadLocal可以避免在方法之間傳遞參數的繁瑣,尤其在跨層傳遞參數的場景中,可以大大簡化代碼。
  3. 線程局部變量:ThreadLocal可以用于在當前線程中存儲和訪問局部變量,例如日志、請求信息等。

實現原理

首先通過一張圖看下ThreadLocal與線程的關系圖:

圖片

  1. 每個Thread對象都有一個ThreadLocalMap類型的成員變量threadLocals,這個變量是一個鍵值對集合,用于存儲每個ThreadLocal對象對應的值。
  2. 每個ThreadLocal對象都有一個唯一的ID,用于在ThreadLocalMap中作為鍵來存儲值。
  3. 當一個線程第一次調用ThreadLocal對象的get()方法時,它會先獲取當前線程的ThreadLocalMap對象,然后以ThreadLocal對象的ID作為鍵,從ThreadLocalMap中獲取對應的值。
  4. 如果ThreadLocalMap中不存在對應的鍵值對,則調用ThreadLocal對象的initialValue()方法來初始化一個值,并將其存儲到ThreadLocalMap中。
  5. 如果ThreadLocalMap對象的引用不再需要,那么需要手動將其置為null,這樣可以避免內存泄漏。

內存泄漏:

ThreadLocal變量副本的生命周期與線程的生命周期一樣長,如果線程長時間存在,而ThreadLocal變量沒有及時清理,就會造成內存泄漏。為了避免內存泄漏,可以在使用ThreadLocal的地方及時清理ThreadLocal變量,例如在線程池中使用ThreadLocal時,需要在線程結束時手動清理ThreadLocal變量。

內存泄漏出現的原因:

ThreadLocalMap中的Entry對象持有ThreadLocal對象的弱引用,但是ThreadLocalMap中的Entry對象是由ThreadLocal對象強引用的。
如果ThreadLocal對象沒有及時清理,在ThreadLocal對象被垃圾回收時,ThreadLocalMap中的Entry對象仍然存在,從而導致內存泄漏。

解決內存泄漏的方法:

在使用ThreadLocal的代碼中及時清理ThreadLocal變量。通常情況下,我們可以使用ThreadLocal的remove()方法手動清理ThreadLocal
變量,或者在使用完ThreadLocal變量后將其設置為null

圖片

通過上圖我們可以看到,在線程方法執行過程中,ThreadLocal、ThreadLocalMap以及Thread之間的引用關系; Thread中存在一個屬性threadLocals指向了ThreadLocalMap,ThreadLocal實現線程級別的數據隔離主要是基于該對象;在ThreadLocal中是沒有存儲任何數據,其更像一個線程與ThreadLocalMap間的協調器,數據存儲在ThreadLocalMap中,但是該Map的Key卻是ThreadLocal的弱引用;

一般情況下,線程執行完成后,待線程銷毀,那么線程對應的屬性threadLocals也會被銷毀;但是真實環境中對線程的使用大部分都是線程池,這樣在整個系統生命周期中, 線程都是有效的,直至線程池關閉。而將ThreadLocalMap的Key設置成弱引用時,經過GC后該Map的Key則變成了null,但是其Value卻一直存在,因此需要手動將key為null 的數據進行清理。

下面是一個示例演示如何避免ThreadLocal內存泄漏:

public class MyThreadLocal {
    
    private static ThreadLocal< String > threadLocal = new ThreadLocal<  >();

    public static void set(String value) {
        threadLocal.set(value);
    }

    public static String get() {
        return threadLocal.get();
    }

    public static void remove() {
        threadLocal.remove();
    }
}

public class MyRunnable implements Runnable {
    
    @Override
    public void run() {
        MyThreadLocal.set("hello");
        System.out.println(MyThreadLocal.get());
        // 在使用完ThreadLocal變量后,調用remove()方法清理ThreadLocal變量
        MyThreadLocal.remove();
    }
}

在上面的代碼中,MyThreadLocal類封裝了ThreadLocal變量的操作,MyRunnable類實現了Runnable接口,使用MyThreadLocal類來存儲和訪問 ThreadLocal變量。在MyRunnable的run()方法中,使用完ThreadLocal變量后,調用remove()方法清理ThreadLocal變量,避免了內存泄漏的問題。


ThreadLocal一般會設置成static

主要是為了避免重復創建TSO(thread specific object,即與線程相關的變量。)我們知道,一個ThreadLocal實例對應當前線程中的一個TSO實例。如果把ThreadLocal聲明為某個類的實例變量(而不是靜態變量),那么每創建一個該類的實例就會導致一個新的TSO實例被創建。而這些被創建的TSO實例是同一個類的實例。同一個線程可能會訪問到同一個TSO(指類)的不同實例,這即便不會導致錯誤,也會導致浪費!

簡單的說就是在ThreadLocalMap中,同一個線程是否有必要設置多個ThreadLocal來存儲線程變量?

示例

下面是一個簡單的例子,演示了如何使用ThreadLocal來實現線程數據隔離:

public class ThreadLocalTest {
    
    private static ThreadLocal< String > threadLocal = new ThreadLocal<  >();

    public static void main(String[] args) throws InterruptedException {
        new Thread(() - > {
            threadLocal.set("Thread A");
            System.out.println("Thread A: " + threadLocal.get());
        }).start();

        new Thread(() - > {
            threadLocal.set("Thread B");
            System.out.println("Thread B: " + threadLocal.get());
        }).start();

        Thread.sleep(1000);

        System.out.println("Main: " + threadLocal.get());
    }
}

運行結果如下:

Thread A: Thread A
Thread B: Thread B
Main: null

從輸出結果可以看出,每個線程都擁有自己的變量副本,互不影響。而在主線程中,由于沒有設置過變量副本,所以返回null。

結束語

ThreadLocal是幫助我們在多個線程間實現線程對數據獨享,并不是用來解決線程間的數據共享問題。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 存儲
    +關注

    關注

    13

    文章

    4317

    瀏覽量

    85872
  • JAVA
    +關注

    關注

    19

    文章

    2969

    瀏覽量

    104783
  • 程序
    +關注

    關注

    117

    文章

    3787

    瀏覽量

    81072
  • 多線程技術
    +關注

    關注

    0

    文章

    12

    瀏覽量

    8560
收藏 人收藏

    評論

    相關推薦

    SQLx的基礎用法和進階用法

    SQLx是一個Rust語言的異步SQL數據庫訪問庫,支持多種數據庫,包括PostgreSQL、MySQL、SQLite等。本教程將以SQLite為例,介紹SQLx的基礎用法和進階用法。 基礎用法
    的頭像 發表于 09-19 14:29 ?2345次閱讀

    Stream模塊的基礎用法和進階用法

    有用。在本教程中,我們將介紹 Stream 模塊的基礎用法和進階用法,并提供示例。 基礎用法 在本節中,我們將介紹 Stream 模塊的基礎用法,并提供基礎示例。 從 Vec 中創建
    的頭像 發表于 09-19 15:33 ?1206次閱讀

    ThreadLocal實例應用

    ThreadLocal相信大家都用過,但你知道他的原理嗎,今天了不起帶大家學習ThreadLocalThreadLocal是什么 在多線程編程中,經常會遇到需要在不同線程中共享數據的情況
    的頭像 發表于 09-30 10:19 ?673次閱讀
    <b class='flag-5'>ThreadLocal</b>實例應用

    用戶自定義終止符EOF用法

    EOF(End OF File)在Linux命令和腳本中表示用戶自定義終止符,其用法如下:
    發表于 07-23 07:18

    狀態機原理及用法

    狀態機原理及用法狀態機原理及用法狀態機原理及用法
    發表于 03-15 15:25 ?0次下載

    Sniffer用法

    Snffer的定義、分類及基本用法步驟,操作成功后的現象、數據包信息
    發表于 05-30 15:08 ?0次下載

    C語言中#define的一些用法介紹概述

    今天整理了一些#define的用法,與大家共享!1.簡單的define定義#define MAXTIME 1
    的頭像 發表于 04-14 11:29 ?7393次閱讀

    ThreadLocal發生內存泄漏的原因

    前言 ThreadLocal 的作用是提供線程內的局部變量,這種變量在線程的生命周期內起作用,減少同一個線程內多個函數或者組件之間一些公共變量的傳遞的復雜度。但是如果濫用 ThreadLocal
    的頭像 發表于 05-05 16:23 ?3684次閱讀

    如何使用ThreadLocal來避免內存泄漏

    本次給大家介紹重要的工具ThreadLocal。講解內容如下,同時介紹什么場景下發生內存泄漏,如何復現內存泄漏,如何正確使用它來避免內存泄漏。 ThreadLocal是什么?有哪些用途
    的頭像 發表于 08-20 09:29 ?4243次閱讀
    如何使用<b class='flag-5'>ThreadLocal</b>來避免內存泄漏

    C語言基礎:宏定義使用do{}while(0)的好處

    C語言宏定義使用do{}while(0)的好處1. 概述 經常寫項目代碼,有時需要用到宏定義,而宏定義用法是否標準,則是會影響到是否能快速查錯以及代碼拓展性的問題。在宏
    發表于 01-13 13:06 ?2次下載
    C語言基礎:宏<b class='flag-5'>定義</b>使用do{}while(0)的好處

    ThreadLocal的作用以及應用場景

    舉一個簡單的例子:目前有100個學生等待簽字,但是老師只有一個筆,那老師只能按順序的分給每個學生,等待A學生簽字完成然后將筆交給B學生,這就類似Lock,Synchronized的方式。而ThreadLocal是,老師直接拿出一百個筆給每個學生;再效率提高的同事也要付出一個內存消耗;也就是以空間換時間的概念
    的頭像 發表于 09-19 10:56 ?1365次閱讀

    ThreadLocal源碼解析及實戰應用

    ThreadLocal 是一個關于創建線程局部變量的類。
    的頭像 發表于 01-29 14:53 ?476次閱讀

    ThreadLocal父子線程之間該如何傳遞數據?

    比如會有以下的這種代碼的實現。在子線程中調用 get 時,我們拿到的 Thread 對象是當前子線程對象,對吧,每個線程都有自己獨立的 ThreadLocal,那么當前子線程
    的頭像 發表于 02-20 11:26 ?916次閱讀

    Java枚舉的特點及用法

    什么是枚舉 Java 枚舉(Enum)是一種特殊的數據類型,它是一組預定義的常量,每個常量都有一個名稱和一個值。 枚舉類型在 Java 中被廣泛使用,它可以用來代替常量、標志位、狀態碼等,使代碼更加清晰、易讀和易維護。 2. 枚舉的優點 類型安全性:枚舉類型可以
    的頭像 發表于 09-30 10:02 ?1458次閱讀

    ThreadLocal基本內容與用法

    的杰作,膜拜一下。怪不得道哥也愛用,自己設計的類總得用用。下面來看看基本內容與用法吧。 2 ThreadLocal原理 “This class provides thread-local
    的頭像 發表于 10-13 11:39 ?466次閱讀
    主站蜘蛛池模板: 榴莲推广APP网站入口下载安装| 九九久久久2| 一本道dvd久久综合高清免费| 色色色五的天| 欧美三级aaa| 女教师の诱惑| 伦理在线影院伦理电影| 久久久久久久久人体| 久草免费视频在线观看| 交换:年轻夫妇-HD中文字幕| 國産麻豆AVMDMD0179| 国产精品久久久久影院色老大| 国产 日韩 欧美 高清 亚洲 | 狠狠干福利视频| 国语自产一区第二页| 精品久久香蕉国产线看观看麻豆 | 日韩免费一区二区三区在线| 欧美亚洲精品午夜福利AV| 欧美激情性AAAAA片欧美 | 色欲AV精品人妻一区二区三区| 日本不卡三卡四卡| 色www.亚洲免费视频| 色欲档案之麻雀台上淫| 特级淫片大乳女子高清视频| 无码AV熟妇素人内射V在线| 我们日本在线观看免费动漫下载| 午夜毛片在线观看| 亚洲你我色| 中文无码第3页不卡av| 1788福利视频在视频线| 99久酒店在线精品2019| 变态露出野外调教| 国产成年网站v片在线观看| 国产免费福利在线视频| 狠狠插综合| 老头狠狠挺进小莹体内视频| 男人的天堂MV在线视频免费观看| 青青草原免费在线| 无修肉动漫在线观看影片| 亚洲男人天堂2018av| 2023国产精品一卡2卡三卡4卡|