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

關(guān)于TransmittableThreadLocal線程池中線程復(fù)用問(wèn)題的解決方案

 更新時(shí)間:2023年11月15日 09:36:06   作者:立小研先森  
這篇文章主要介紹了關(guān)于TransmittableThreadLocal線程池中線程復(fù)用問(wèn)題的解決方案,線程池復(fù)用線程,如果子線程執(zhí)行完未移除上下文,則會(huì)導(dǎo)致后續(xù)線程可以取到之前線程設(shè)置的屬性,需要的朋友可以參考下

TransmittableThreadLocal線程復(fù)用問(wèn)題

TTL對(duì)線程或者線程池的核心通過(guò)裝飾器模式做了處理,核心如下:

  • capture:獲取父線程中的值,包括引用對(duì)象或普通對(duì)象
  • replay:回放:備份、將父線程的值設(shè)置到子線程
  • restore:將子線程執(zhí)行之前backup的值設(shè)置回子線程的ThreadLocal

一、TTL在線程池場(chǎng)景

線程池復(fù)用線程,如果子線程執(zhí)行完未移除上下文,則會(huì)導(dǎo)致后續(xù)線程可以取到之前線程設(shè)置的屬性

public class TtlErrorTest {
    private static final TransmittableThreadLocal<User> context = new TransmittableThreadLocal<>();
    
    private static final ExecutorService service = Executors.newSingleThreadExecutor();
  //TTL修飾過(guò)的線程池(1)
//  private static final Executor service = TtlExecutors.getTtlExecutor(Executors.newSingleThreadExecutor());

    public static void main(String[] args) {
      	//主線程設(shè)置上下文變量(3)
        //User user1 = new User();
        //user1.setUsername("孫少平");
        //user1.setPassword("123456");
        //context.set(user1);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                User user = new User();
                user.setUsername("田曉霞");
                context.set(user);
                System.out.println("1-" + Thread.currentThread().getName() + ":" + context.get());
                //移除上下文變量(2)
                //context.remove();
            }
        };
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("2-" + Thread.currentThread().getName() + ":" + context.get());
            }
        };
        service.execute(runnable);
        service.execute(runnable1);
       //移除上下文(4)
        //ntext.remove();
    }
}

結(jié)果一:

1-pool-1-thread-1:田曉霞
2-pool-1-thread-1:田曉霞

結(jié)果二(將代碼中的(1)(3)打開(kāi)運(yùn)行):

1-pool-1-thread-1:田曉霞
2-pool-1-thread-1:孫少平

分析:上述案例定義了只有一個(gè)工作線程執(zhí)行隊(duì)列中線程的線程池,這樣做是為了立馬復(fù)現(xiàn)線程復(fù)用的效果;第一個(gè)線程中第一了上下文值引用對(duì)象,第二個(gè)線程之中沒(méi)有定義,效果是第二個(gè)線程獲取到了第一個(gè)線程之中設(shè)置的上下文變量;如果將第一個(gè)線程中(2)注釋打開(kāi),則第二個(gè)線程獲取不到第一個(gè)線程中設(shè)置的上下文變量;

如果將(1)打開(kāi)會(huì)是什么效果,效果是第二個(gè)線程拿不到第一個(gè)線程中設(shè)置的上下文值,這又是為什么呢?在第一個(gè)線程中又沒(méi)有主動(dòng)remove掉為何使用了TTL修飾的線程池就拿不到符合預(yù)期了呢?

如果仔細(xì)分析源碼會(huì)發(fā)現(xiàn)TTL修飾的線程使用裝飾器模式,第一步capture捕獲主線程上下文,第二部replay回放、backup備份子線程上下文、將主線程上下文值設(shè)置到子線程,第三部restore恢復(fù)階段、將backup備份恢復(fù)到子線程上下文,因?yàn)樽泳€程上下文執(zhí)行沒(méi)有任何值,restore恢復(fù)后上下文是干凈的,上下文沒(méi)有任何值;那在第二個(gè)線程復(fù)用線程的時(shí)候是取不到指的,符合預(yù)期;

如果將(1)(3)打開(kāi)運(yùn)行結(jié)果也是符合預(yù)期的,這里面有個(gè)問(wèn)題,無(wú)論線程一、線程二執(zhí)行完成后線程池中復(fù)用的線程都會(huì)持有一個(gè)User對(duì)象的引用,這樣GC的時(shí)候就無(wú)法回收資源,如果線程池持有的引用對(duì)象足夠多,引用對(duì)象占用的內(nèi)存足夠大的時(shí)候就有可能引發(fā)OOM異常;

如果將代碼(4)打開(kāi)則會(huì)移除主線程的上下文,但是子線程從父線程繼承的上下文屬性是無(wú)法移除的;

二、TTL如何保證線程池中復(fù)用的線程不持有其它線程的屬性值

針對(duì)上述線程池復(fù)用可能導(dǎo)致內(nèi)存OOM的問(wèn)題提供了兩種解決方案

方案一:通過(guò)TtlExecutors.getDefaultDisableInheritableThreadFactory()在線程池中創(chuàng)建禁止繼承父線程上下文的線程

public class TtlFactoryTest {
    private static final TransmittableThreadLocal<User> context = new TransmittableThreadLocal<>();
    static final ExecutorService service = Executors.newFixedThreadPool(2, TtlExecutors.getDefaultDisableInheritableThreadFactory());
    public static void main(String[] args) {
        User user = new User();
        user.setUsername("田曉霞");
        context.set(user);
        System.out.println("1-" + Thread.currentThread().getName() + "-" + context.get());
        service.submit(new Runnable() {
            @Override
            public void run() {
                User user1 = new User();
                user1.setUsername("田二");
                context.set(user1);
                System.out.println("2-" + Thread.currentThread().getName() + "-" + context.get());
            }
        });
        System.out.println("3-" + Thread.currentThread().getName() + "-" + context.get());
    }
}

方案二:去除掉父子線程的繼承關(guān)系,相當(dāng)于TTL由InheritableThreadLocal回退到了ThreadLocal

TransmittableThreadLocal<String> t1 = new TransmittableThreadLocal<String>() {
    protected String childValue(String parentValue) {
        return initialValue();
    }
}

此方法是去除掉父子線程之間的繼承關(guān)系,會(huì)將TTL回退到ThreadLocal,對(duì)于非線程池的父子線程繼承關(guān)系是不適用的;

到此這篇關(guān)于關(guān)于TransmittableThreadLocal線程池中線程復(fù)用問(wèn)題的解決方案的文章就介紹到這了,更多相關(guān)TransmittableThreadLocal線程復(fù)用問(wèn)題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JavaWeb詳細(xì)講述Cookie和Session的概念

    JavaWeb詳細(xì)講述Cookie和Session的概念

    web開(kāi)發(fā)階段我們主要是瀏覽器和服務(wù)器之間來(lái)進(jìn)行交互。瀏覽器和服務(wù)器之間的交互就像人和人之間進(jìn)行交流一樣,但是對(duì)于機(jī)器來(lái)說(shuō),在一次請(qǐng)求之間只是會(huì)攜帶著本次請(qǐng)求的數(shù)據(jù)的,但是可能多次請(qǐng)求之間是會(huì)有聯(lián)系的,所以提供了會(huì)話機(jī)制
    2022-06-06
  • Java多線程死鎖示例

    Java多線程死鎖示例

    這篇文章主要介紹了Java多線程死鎖,結(jié)合實(shí)例形式分析了Java多線程出現(xiàn)死鎖的相關(guān)原因與操作注意事項(xiàng),需要的朋友可以參考下
    2018-08-08
  • Spring實(shí)例化bean的方式大全

    Spring實(shí)例化bean的方式大全

    Spring 實(shí)例化 Bean 主要有三種核心方式:構(gòu)造器實(shí)例化、靜態(tài)工廠方法實(shí)例化和實(shí)例工廠方法實(shí)例化,其中構(gòu)造器實(shí)例化是最常用的方式,下面小編給大家詳細(xì)說(shuō)說(shuō)這幾種方式,需要的朋友可以參考下
    2025-09-09
  • 基于@PathVariable注解的用法說(shuō)明

    基于@PathVariable注解的用法說(shuō)明

    這篇文章主要介紹了基于@PathVariable注解的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • Java String類的常用方法匯總

    Java String類的常用方法匯總

    這篇文章主要為大家詳細(xì)匯總了Java String類的常用方法,感興趣的小伙伴們可以參考一下
    2016-07-07
  • ssm框架+PageHelper插件實(shí)現(xiàn)分頁(yè)查詢功能

    ssm框架+PageHelper插件實(shí)現(xiàn)分頁(yè)查詢功能

    今天小編教大家如何通過(guò)ssm框架+PageHelper插件實(shí)現(xiàn)分頁(yè)查詢功能,首先大家需要新建一個(gè)maven工程引入jar包,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-06-06
  • 詳解Java實(shí)踐之抽象工廠模式

    詳解Java實(shí)踐之抽象工廠模式

    抽象工廠模式用于產(chǎn)品族的構(gòu)建。抽象工廠是所有形態(tài)的工廠模式中最為抽象和最具一般性的一種形態(tài)。抽象工廠是指當(dāng)有多個(gè)抽象角色時(shí)使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個(gè)接口,使客戶端在不必指定產(chǎn)品的具體情況下,創(chuàng)建多個(gè)產(chǎn)品族中的產(chǎn)品對(duì)象
    2021-06-06
  • Java使用jacob將微軟office中word、excel、ppt轉(zhuǎn)成pdf

    Java使用jacob將微軟office中word、excel、ppt轉(zhuǎn)成pdf

    這篇文章主要為大家詳細(xì)介紹了Java使用jacob將微軟office中word、excel、ppt轉(zhuǎn)成pdf,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • Java 8中字符串拼接新姿勢(shì)StringJoiner詳解

    Java 8中字符串拼接新姿勢(shì)StringJoiner詳解

    在本篇文章里小編給大家整理了關(guān)于Java 8中字符串拼接新姿勢(shì)StringJoiner的詳解內(nèi)容,需要的朋友們參考下。
    2019-09-09
  • Java Spring三級(jí)緩存

    Java Spring三級(jí)緩存

    三級(jí)緩存就是在Bean生成流程中保存Bean對(duì)象三種形態(tài)的三個(gè)Map集合,這個(gè)三級(jí)緩存就是為了解決循環(huán)依賴,本文給大家介紹Java Spring三級(jí)緩存,感興趣的朋友一起看看吧
    2025-06-06

最新評(píng)論

繁峙县| 磐安县| 镇江市| 桂东县| 永嘉县| 汽车| 临沭县| 扶绥县| 济源市| 安庆市| 宕昌县| 鄱阳县| 喀喇沁旗| 隆子县| 民乐县| 读书| 雷山县| 平阳县| 潍坊市| 大田县| 桑日县| 天柱县| 故城县| 湘阴县| 托克逊县| 上高县| 临湘市| 德江县| 行唐县| 东乡县| 巴彦县| 鸡泽县| 香港| 保亭| 五莲县| 开封市| 交城县| 敖汉旗| 宜章县| 从江县| 平定县|