最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java ThreadLocal 線程本地存儲(chǔ)工具思路詳解

 更新時(shí)間:2025年12月12日 10:52:26   作者:heartbeat..  
文章詳細(xì)介紹了Java的ThreadLocal類,包括其核心作用、定位、特性、工作原理、用法、內(nèi)存泄漏風(fēng)險(xiǎn)、父子線程共享問(wèn)題、線程安全邊界以及與synchronized和并發(fā)容器的區(qū)別,感興趣的朋友跟隨小編一起看看吧

ThreadLocal 詳解:Java 線程本地存儲(chǔ)工具

一、介紹

ThreadLocal 是 Java 提供的線程本地存儲(chǔ)(Thread-Local Storage, TLS)工具類,核心作用是為每個(gè)線程創(chuàng)建獨(dú)立的變量副本,讓線程操作自己獨(dú)有的數(shù)據(jù),實(shí)現(xiàn)線程間狀態(tài)隔離,避免多線程共享變量的競(jìng)爭(zhēng)問(wèn)題。

二、定位

1. 思路

多線程環(huán)境中,共享變量(如靜態(tài)變量、成員變量)會(huì)引發(fā)線程安全問(wèn)題(需加鎖 synchronized 或用并發(fā)容器),但加鎖會(huì)導(dǎo)致性能損耗。而 ThreadLocal 換了一種思路:不共享變量,給每個(gè)線程分配獨(dú)立副本,從根源避免競(jìng)爭(zhēng)。

2. 特性

  • 線程隔離:每個(gè)線程的 ThreadLocal 變量副本完全獨(dú)立,線程 A 修改自己的副本不會(huì)影響線程 B 的副本;
  • 懶初始化:變量副本默認(rèn)不會(huì)主動(dòng)創(chuàng)建,僅在線程首次訪問(wèn)時(shí)初始化;
  • 全局訪問(wèn):通過(guò) ThreadLocal 實(shí)例可在線程的任意方法、任意層級(jí)中訪問(wèn)當(dāng)前線程的副本(無(wú)需參數(shù)傳遞)。

3.原理

ThreadLocal 的線程隔離特性,依賴 Java 中 Thread 類的內(nèi)部結(jié)構(gòu),核心是 ThreadThreadLocalMap 的關(guān)聯(lián)

  • Thread 類:每個(gè) Thread 實(shí)例內(nèi)部都持有一個(gè) ThreadLocalMap 成員變量(哈希表),專門存儲(chǔ)當(dāng)前線程的「ThreadLocal- 變量副本」映射;
  • ThreadLocalMapThreadLocal 的內(nèi)部靜態(tài)類,本質(zhì)是哈希表(解決哈希沖突用「開(kāi)放地址法」,而非 HashMap 的鏈表 / 紅黑樹(shù)),鍵是 ThreadLocal 實(shí)例(弱引用),值是線程的變量副本(強(qiáng)引用);
  • 弱引用設(shè)計(jì):ThreadLocalMap 的鍵(ThreadLocal)是弱引用(WeakReference),目的是:當(dāng) ThreadLocal 實(shí)例本身被回收時(shí)(如不再有強(qiáng)引用指向它),避免因哈希表持有強(qiáng)引用導(dǎo)致 ThreadLocal 無(wú)法 GC。

簡(jiǎn)單舉出一個(gè)例子:

當(dāng)線程調(diào)用 threadLocal.get() 時(shí),底層執(zhí)行步驟:

  1. 獲取當(dāng)前線程:Thread currentThread = Thread.currentThread();
  2. 從當(dāng)前線程中獲取 ThreadLocalMapThreadLocalMap map = currentThread.threadLocals;
  3. map 存在且包含當(dāng)前 ThreadLocal 對(duì)應(yīng)的鍵,則直接返回對(duì)應(yīng)的變量副本(值);
  4. 若map不存在,或無(wú)對(duì)應(yīng)鍵(線程首次訪問(wèn)):
    • 執(zhí)行初始化邏輯(withInitial 的 lambda 或 initialValue() 方法)創(chuàng)建變量副本;
    • 初始化當(dāng)前線程的 ThreadLocalMap,并將「ThreadLocal- 副本」映射存入 map;
  5. 返回變量副本。
線程1 → Thread.threadLocals(ThreadLocalMap)→ { ThreadLocal實(shí)例: 線程1的變量副本 }
線程2 → Thread.threadLocals(ThreadLocalMap)→ { ThreadLocal實(shí)例: 線程2的變量副本 }
線程3 → Thread.threadLocals(ThreadLocalMap)→ { ThreadLocal實(shí)例: 線程3的變量副本 }

多個(gè)線程共享同一個(gè) ThreadLocal 實(shí)例,但各自的 ThreadLocalMap 獨(dú)立,副本互不干擾。

4.補(bǔ)充一下變量副本的概念:

變量副本(也叫「副本變量」「拷貝實(shí)例」),本質(zhì)是 原變量(或?qū)ο螅┑囊环莳?dú)立拷貝—— 它和原變量的「數(shù)據(jù)內(nèi)容初始一致」,但擁有獨(dú)立的內(nèi)存空間,后續(xù)對(duì)副本的修改不會(huì)影響原變量,反之亦然。

假設(shè)你有一份「原始合同」(對(duì)應(yīng)「原變量」):

  1. 你給同事復(fù)印了一份(對(duì)應(yīng)「創(chuàng)建副本」):兩份文件內(nèi)容完全一樣;
  2. 同事在自己的復(fù)印件上修改了條款(對(duì)應(yīng)「修改副本」):你的原始合同不受任何影響;
  3. 你在原始合同上補(bǔ)充了內(nèi)容(對(duì)應(yīng)「修改原變量」):同事的復(fù)印件也不會(huì)同步變化;
  4. 同事弄丟了自己的復(fù)印件(對(duì)應(yīng)「銷毀副本」):你的原始合同依然存在。

副本和原變量相互獨(dú)立,修改、銷毀互不干擾。

  • 引用傳遞:多個(gè)線程持有同一個(gè)對(duì)象的引用(指向同一塊內(nèi)存),修改會(huì)相互影響(線程不安全);
  • 副本傳遞:多個(gè)線程持有不同對(duì)象的引用(指向不同內(nèi)存),修改互不影響(線程安全)。

ThreadLocal 存儲(chǔ)的是「對(duì)象級(jí)別的副本」—— 每個(gè)線程拿到的是「同一個(gè)類的新實(shí)例」(而非同一個(gè)對(duì)象的引用),本質(zhì)是「對(duì)象的深拷貝 / 新實(shí)例化」,擁有獨(dú)立的內(nèi)存空間,還有另一種就是普通的值傳遞。

三、用法

ThreadLocal 的 API 極簡(jiǎn),核心只有 4 個(gè)方法,結(jié)合 Java 8+ 的簡(jiǎn)化用法:

1. 初始化:創(chuàng)建ThreadLocal實(shí)例

有兩種初始化方式,推薦 Java 8+ 的 withInitial(函數(shù)式接口,代碼更簡(jiǎn)潔):

// 方式1:Java 8+ 推薦(懶初始化,線程首次get()時(shí)執(zhí)行)
ThreadLocal<GlobalContext> threadLocal = ThreadLocal.withInitial(() -> {
    GlobalContext context = new GlobalContext();
    context.user = new SessionUser(); // 初始化副本數(shù)據(jù)
    return context;
});
// 方式2:Java 8 前(重寫 initialValue() 方法)
ThreadLocal<GlobalContext> threadLocal = new ThreadLocal<GlobalContext>() {
    @Override
    protected GlobalContext initialValue() {
        GlobalContext context = new GlobalContext();
        context.user = new SessionUser();
        return context;
    }
};

2. 獲取副本:get()

獲取當(dāng)前線程的變量副本,首次調(diào)用會(huì)觸發(fā)初始化:

GlobalContext context = threadLocal.get(); // 線程獨(dú)有的副本

3. 設(shè)置副本:set(T value)

主動(dòng)給當(dāng)前線程設(shè)置變量副本(覆蓋默認(rèn)初始化的副本):

GlobalContext customContext = new GlobalContext();
customContext.user = new SessionUser("admin", "管理員");
threadLocal.set(customContext); // 替換當(dāng)前線程的副本

4. 清除副本:remove()

刪除當(dāng)前線程的變量副本(解決內(nèi)存泄漏的關(guān)鍵):

threadLocal.remove(); // 線程使用完畢后必須調(diào)用!

補(bǔ)充一下內(nèi)存泄漏:

內(nèi)存泄漏(Memory Leak):程序中不再使用的對(duì)象,因?yàn)楸诲e(cuò)誤地持有了 “無(wú)法釋放的引用”,導(dǎo)致垃圾回收器(GC)不能回收它,最終這些對(duì)象占滿內(nèi)存,引發(fā)程序卡頓、OOM(內(nèi)存溢出)崩潰。

簡(jiǎn)單舉個(gè)例子:

你買了一箱水果(對(duì)應(yīng) “對(duì)象”),吃完后箱子沒(méi)用了(對(duì)應(yīng) “對(duì)象不再被使用”),但你一直把箱子鎖在柜子里(對(duì)應(yīng) “被無(wú)效引用持有”),柜子空間被占著,后續(xù)再買東西就沒(méi)地方放,最后柜子徹底堆滿(對(duì)應(yīng) “內(nèi)存耗盡”)。

5. 實(shí)用封裝(實(shí)際開(kāi)發(fā)常用)

通常會(huì)將 ThreadLocal 封裝為靜態(tài)工具類,方便全局訪問(wèn)和統(tǒng)一清理:

public class ContextHolder {
    // 私有靜態(tài) ThreadLocal 實(shí)例(全局唯一)
    private static final ThreadLocal<GlobalContext> THREAD_LOCAL = ThreadLocal.withInitial(() -> {
        GlobalContext context = new GlobalContext();
        context.user = new SessionUser();
        return context;
    });
    // 靜態(tài)方法:獲取當(dāng)前線程上下文
    public static GlobalContext getContext() {
        return THREAD_LOCAL.get();
    }
    // 靜態(tài)方法:設(shè)置用戶信息(示例)
    public static void setUser(SessionUser user) {
        getContext().user = user;
    }
    // 靜態(tài)方法:清除上下文(必須調(diào)用?。?
    public static void clear() {
        THREAD_LOCAL.remove();
    }
}

四、典型使用場(chǎng)景

ThreadLocal 最適合「線程級(jí)別的上下文傳遞」,無(wú)需層層傳遞參數(shù),常見(jiàn)場(chǎng)景:

Web 應(yīng)用:請(qǐng)求上下文傳遞

  • 存儲(chǔ)當(dāng)前 HTTP 請(qǐng)求的用戶信息(登錄狀態(tài)、權(quán)限)、請(qǐng)求 ID(日志追蹤)、Token 等;
  • 貫穿鏈路:Controller → Service → DAO,無(wú)需在每個(gè)方法參數(shù)中顯式聲明上下文。
// Spring MVC 攔截器示例:請(qǐng)求開(kāi)始時(shí)設(shè)置上下文,結(jié)束時(shí)清除
public class ContextInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 從請(qǐng)求頭獲取用戶信息,設(shè)置到 ThreadLocal
        SessionUser user = new SessionUser(request.getHeader("userId"));
        ContextHolder.setUser(user);
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 請(qǐng)求結(jié)束,清除上下文(避免內(nèi)存泄漏)
        ContextHolder.clear();
    }
}

多線程任務(wù):線程池上下文隔離

  • 線程池中的核心線程長(zhǎng)期存活,每個(gè)任務(wù)線程需要獨(dú)立的配置(如數(shù)據(jù)庫(kù)連接、日志標(biāo)識(shí));
  • 注意:任務(wù)執(zhí)行完畢后必須調(diào)用 remove(),否則核心線程會(huì)持有副本導(dǎo)致內(nèi)存泄漏。

框架底層:狀態(tài)隔離

  • Spring 事務(wù)管理:TransactionSynchronizationManagerThreadLocal 存儲(chǔ)當(dāng)前線程的事務(wù)狀態(tài);
  • MyBatis:用 ThreadLocal 存儲(chǔ)當(dāng)前線程的 SqlSession(數(shù)據(jù)庫(kù)會(huì)話)。

五、注意

1. 內(nèi)存泄漏風(fēng)險(xiǎn)

為什么會(huì)內(nèi)存泄漏?
  • ThreadLocalMap 的鍵(ThreadLocal)是弱引用:當(dāng) ThreadLocal 實(shí)例被回收(如工具類被卸載),鍵會(huì)變成 null;
  • ThreadLocalMap 的值(變量副本)是強(qiáng)引用:若線程長(zhǎng)期存活(如線程池核心線程),null 鍵對(duì)應(yīng)的 value 無(wú)法被 GC,導(dǎo)致內(nèi)存泄漏。
解決方案
  • 線程使用完畢后,主動(dòng)調(diào)用 remove():刪除 ThreadLocalMap 中的 value,是最穩(wěn)妥的方式;
  • 避免使用 static ThreadLocal 長(zhǎng)期持有強(qiáng)引用(若必須用,務(wù)必在合適時(shí)機(jī) remove());
  • 不建議用「弱引用包裝 value」(易導(dǎo)致空指針,治標(biāo)不治本)。

2. 線程復(fù)用場(chǎng)景的坑(線程池)

線程池中的線程會(huì)被復(fù)用(如核心線程),若上一個(gè)任務(wù)未調(diào)用 remove(),下一個(gè)任務(wù)會(huì)復(fù)用上一個(gè)任務(wù)的變量副本,導(dǎo)致數(shù)據(jù)污染:

// 錯(cuò)誤示例:線程池任務(wù)未清除 ThreadLocal
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(() -> {
    ContextHolder.getContext().user.setUserId("1001"); // 任務(wù)1設(shè)置用戶1001
    // 未調(diào)用 ContextHolder.clear()!
});
executor.submit(() -> {
    String userId = ContextHolder.getContext().user.getUserId();
    System.out.println(userId); // 輸出 1001(數(shù)據(jù)污染,預(yù)期應(yīng)是默認(rèn)值)
});

解決:任務(wù)執(zhí)行完畢后必須調(diào)用 remove(),或在任務(wù)開(kāi)始時(shí)主動(dòng) set() 覆蓋舊值。

3. 父子線程共享問(wèn)題

ThreadLocal 不支持父子線程共享副本(父線程的副本,子線程無(wú)法直接獲取)。若需要父子線程共享,需使用 InheritableThreadLocal(繼承自 ThreadLocal):

// 父子線程共享示例
InheritableThreadLocal<GlobalContext> inheritableTl = new InheritableThreadLocal<>();
inheritableTl.set(new GlobalContext(new SessionUser("父線程用戶")));
new Thread(() -> {
    GlobalContext context = inheritableTl.get();
    System.out.println(context.user.getUserId()); // 輸出 "父線程用戶"(子線程繼承父線程副本)
}).start();

注意:InheritableThreadLocal 僅在子線程創(chuàng)建時(shí)復(fù)制父線程的副本,子線程創(chuàng)建后父線程修改副本,子線程不會(huì)同步更新。

4. 線程安全的邊界

ThreadLocal 僅保證「變量副本的線程隔離」,若副本本身是線程共享對(duì)象(如靜態(tài)可變對(duì)象),仍會(huì)有線程安全問(wèn)題:

// 錯(cuò)誤示例:副本是共享對(duì)象
static class GlobalContext {
    public static SessionUser sharedUser; // 靜態(tài)變量(線程共享)
}
ThreadLocal<GlobalContext> threadLocal = ThreadLocal.withInitial(GlobalContext::new);
// 線程1修改靜態(tài)變量,線程2會(huì)受影響
new Thread(() -> threadLocal.get().sharedUser = new SessionUser("1001")).start();
new Thread(() -> System.out.println(threadLocal.get().sharedUser.getUserId())).start(); // 可能輸出 1001

六、補(bǔ)充:

ThreadLocal 與 synchronized / 并發(fā)容器的區(qū)別
  • ThreadLocal:「不共享,各用各的」—— 給每個(gè)線程分配獨(dú)立變量副本,從根源避免競(jìng)爭(zhēng);
  • synchronized:「共享但串行化」—— 通過(guò)互斥鎖限制線程并發(fā)訪問(wèn),同一時(shí)間僅一個(gè)線程操作共享資源;
  • 并發(fā)容器(如 ConcurrentHashMap、CopyOnWriteArrayList):「共享且高效并發(fā)」—— 內(nèi)部封裝鎖 / 無(wú)鎖算法,提供線程安全的集合操作,無(wú)需手動(dòng)加鎖。
對(duì)比維度ThreadLocalsynchronized并發(fā)容器(如 ConcurrentHashMap)
核心設(shè)計(jì)思路線程隔離:每個(gè)線程持獨(dú)立副本,無(wú)共享互斥同步:串行化訪問(wèn)共享資源安全封裝:內(nèi)部集成鎖 / 無(wú)鎖算法,支持并發(fā)訪問(wèn)共享集合
線程安全保障方式天然安全(副本獨(dú)立,無(wú)競(jìng)爭(zhēng))鎖阻塞:未獲取鎖的線程進(jìn)入 BLOCKED 狀態(tài)分段鎖 / 無(wú)鎖 / CAS:減少鎖競(jìng)爭(zhēng),支持多線程并行操作
共享性線程間數(shù)據(jù)不共享(副本隔離)線程間共享同一資源線程間共享同一集合資源
是否需要手動(dòng)控制鎖不需要(無(wú)鎖機(jī)制)需要(手動(dòng)加鎖 / 釋放,JVM 自動(dòng)管理鎖生命周期)不需要(內(nèi)部封裝鎖邏輯,對(duì)外透明)
性能特點(diǎn)無(wú)鎖開(kāi)銷,性能極高(僅操作本地副本)有鎖競(jìng)爭(zhēng)開(kāi)銷,線程阻塞 / 喚醒有成本低競(jìng)爭(zhēng)開(kāi)銷,支持并行操作,性能優(yōu)于 synchronized + 普通集合
數(shù)據(jù)一致性無(wú)一致性問(wèn)題(各線程操作自己的副本)強(qiáng)一致性(同一時(shí)間僅一個(gè)線程修改,結(jié)果唯一)多數(shù)是「最終一致性」(如 ConcurrentHashMap),部分是強(qiáng)一致性(如 CopyOnWriteArrayList)
內(nèi)存開(kāi)銷線程越多,副本越多,內(nèi)存開(kāi)銷越大無(wú)額外內(nèi)存開(kāi)銷(僅占用鎖對(duì)象資源)可能有額外內(nèi)存開(kāi)銷(如分段鎖的段結(jié)構(gòu)、CopyOnWrite 的副本數(shù)組)
典型使用場(chǎng)景線程上下文傳遞(用戶信息、請(qǐng)求 ID)保護(hù)自定義共享資源(如普通對(duì)象、普通集合)多線程并發(fā)讀寫共享集合(如緩存、配置存儲(chǔ))

簡(jiǎn)單概括

  • ThreadLocal:「隔離式」—— 無(wú)鎖、線程私有、不共享,適合上下文傳遞;
  • synchronized:「串行式」—— 悲觀鎖、共享資源、強(qiáng)一致,適合自定義共享資源保護(hù);
  • 并發(fā)容器:「并發(fā)式」—— 封裝鎖 / 無(wú)鎖、共享集合、高效,適合多線程讀寫共享集合。

到此這篇關(guān)于Java ThreadLocal 線程本地存儲(chǔ)工具的文章就介紹到這了,更多相關(guān)Java ThreadLocal 線程本地存儲(chǔ)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解如何在Java中重寫equals()和hashCode()方法

    詳解如何在Java中重寫equals()和hashCode()方法

    在 Java 中,equals() 和 hashCode() 方法是 Object 類中定義的重要方法,它們用于比較對(duì)象的相等性以及計(jì)算對(duì)象的哈希值,本文將詳細(xì)介紹如何在 Java 中重寫 equals() 和 hashCode() 方法,并討論其最佳實(shí)踐,需要的朋友可以參考下
    2024-08-08
  • 完美解決SpringCloud-OpenFeign使用okhttp替換不生效問(wèn)題

    完美解決SpringCloud-OpenFeign使用okhttp替換不生效問(wèn)題

    這篇文章主要介紹了完美解決SpringCloud-OpenFeign使用okhttp替換不生效問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • java使用google身份驗(yàn)證器實(shí)現(xiàn)動(dòng)態(tài)口令驗(yàn)證的示例

    java使用google身份驗(yàn)證器實(shí)現(xiàn)動(dòng)態(tài)口令驗(yàn)證的示例

    本篇文章主要介紹了java使用google身份驗(yàn)證器實(shí)現(xiàn)動(dòng)態(tài)口令驗(yàn)證的示例,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08
  • SpringBoot?自定義starter?yaml提示失效問(wèn)題及解決方法

    SpringBoot?自定義starter?yaml提示失效問(wèn)題及解決方法

    在自定義starter后,必不可少會(huì)有properties配置參數(shù)需要指定,而在有時(shí)又不知道為什么出現(xiàn)這個(gè)問(wèn)題,這篇文章主要介紹了SpringBoot?自定義starter?yaml提示失效問(wèn)題,需要的朋友可以參考下
    2022-12-12
  • Java基礎(chǔ)入門語(yǔ)法--String類

    Java基礎(chǔ)入門語(yǔ)法--String類

    字符串廣泛應(yīng)用在Java編程中,在Java中字符串屬于對(duì)象,Java 提供了String類來(lái)創(chuàng)建和操作字符串,今天給大家介紹Java基礎(chǔ)入門語(yǔ)法--String類的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-06-06
  • 關(guān)于SpringMVC在Controller層方法的參數(shù)解析詳解

    關(guān)于SpringMVC在Controller層方法的參數(shù)解析詳解

    在SpringMVC中,控制器Controller負(fù)責(zé)處理由DispatcherServlet分發(fā)的請(qǐng)求,下面這篇文章主要給大家介紹了關(guān)于SpringMVC在Controller層方法的參數(shù)解析的相關(guān)資料,需要的朋友可以參考下
    2021-12-12
  • sa-token?路由攔截式鑒權(quán)使用示例詳解

    sa-token?路由攔截式鑒權(quán)使用示例詳解

    這篇文章主要為大家介紹了sa-token?路由攔截式鑒權(quán)使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • Activiti流程文件部署過(guò)程解析

    Activiti流程文件部署過(guò)程解析

    這篇文章主要介紹了Activiti流程文件部署過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 關(guān)于maven pom文件配置加載lib下的jar包

    關(guān)于maven pom文件配置加載lib下的jar包

    在項(xiàng)目中引用放置在lib文件夾中的第三方j(luò)ar包需要通過(guò)POM文件進(jìn)行特定配置,雖然將依賴放置在公司的Maven私服是更好的做法,但如果遇到部署問(wèn)題,可以利用maven-jar-plugin進(jìn)行配置,Spring Boot項(xiàng)目可以通過(guò)特定設(shè)置來(lái)實(shí)現(xiàn)
    2024-09-09
  • mybatis使用collection嵌套查詢的實(shí)現(xiàn)

    mybatis使用collection嵌套查詢的實(shí)現(xiàn)

    本文主要介紹了mybatis使用collection嵌套查詢的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05

最新評(píng)論

湖北省| 镇平县| 灵寿县| 安达市| 论坛| 林周县| 秀山| 疏勒县| 许昌市| 红安县| 兴化市| 远安县| 朔州市| 孝感市| 黑水县| 连南| 彝良县| 宜川县| 汤原县| 贵州省| 宝兴县| 册亨县| 武威市| 荣成市| 容城县| 通江县| 原阳县| 明光市| 涿州市| 安平县| 勐海县| 玉林市| 台安县| 遵义市| 沛县| 民乐县| 牙克石市| 聂荣县| 高雄市| 虹口区| 贡山|