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

SpringBoot父子線程數(shù)據(jù)傳遞的五種方案介紹

 更新時間:2022年09月19日 17:05:23   作者:π大星的日常  
在實際開發(fā)過程中我們需要父子之間傳遞一些數(shù)據(jù),比如用戶信息等。該文章從5種解決方案解決父子之間數(shù)據(jù)傳遞困擾,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧

方案1.ThreadLocal+TaskDecorator

用戶工具類 UserUtils

/**
 *使用ThreadLocal存儲共享的數(shù)據(jù)變量,如登錄的用戶信息
 */
public class UserUtils {
    private static  final  ThreadLocal<String> userLocal=new ThreadLocal<>();
    public static  String getUserId(){
        return userLocal.get();
    }
    public static void setUserId(String userId){
        userLocal.set(userId);
    }
    public static void clear(){
        userLocal.remove();
    }
}

自定義CustomTaskDecorator

/**
 * 線程池修飾類
 */
public class CustomTaskDecorator implements TaskDecorator {
    @Override
    public Runnable decorate(Runnable runnable) {
        // 獲取主線程中的請求信息(我們的用戶信息也放在里面)
        String robotId = UserUtils.getUserId();
        System.out.println(robotId);
        return () -> {
            try {
                // 將主線程的請求信息,設(shè)置到子線程中
                UserUtils.setUserId(robotId);
                // 執(zhí)行子線程,這一步不要忘了
                runnable.run();
            } finally {
                // 線程結(jié)束,清空這些信息,否則可能造成內(nèi)存泄漏
                UserUtils.clear();
            }
        };
    }
}

ExecutorConfig

在原來的基礎(chǔ)上增加 executor.setTaskDecorator(new CustomTaskDecorator());

@Bean(name = "asyncServiceExecutor")
    public Executor asyncServiceExecutor() {
        log.info("start asyncServiceExecutor----------------");
        //ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //使用可視化運行狀態(tài)的線程池
        ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
        //配置核心線程數(shù)
        executor.setCorePoolSize(corePoolSize);
        //配置最大線程數(shù)
        executor.setMaxPoolSize(maxPoolSize);
        //配置隊列大小
        executor.setQueueCapacity(queueCapacity);
        //配置線程池中的線程的名稱前綴
        executor.setThreadNamePrefix(namePrefix);
        // rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時候,如何處理新任務(wù)
        // CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是有調(diào)用者所在的線程來執(zhí)行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //增加線程池修飾類
        executor.setTaskDecorator(new CustomTaskDecorator());
        //增加MDC的線程池修飾類
        //executor.setTaskDecorator(new MDCTaskDecorator());
        //執(zhí)行初始化
        executor.initialize();
        log.info("end asyncServiceExecutor------------");
        return executor;
    }

AsyncServiceImpl

    /**
     * 使用ThreadLocal方式傳遞
     * 帶有返回值
     * @throws InterruptedException
     */
    @Async("asyncServiceExecutor")
    public CompletableFuture<String> executeValueAsync2() throws InterruptedException {
        log.info("start executeValueAsync");
        System.out.println("異步線程執(zhí)行返回結(jié)果......+");
        log.info("end executeValueAsync");
        return CompletableFuture.completedFuture(UserUtils.getUserId());
    }

Test2Controller

    /**
     * 使用ThreadLocal+TaskDecorator的方式
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @GetMapping("/test2")
    public String test2() throws InterruptedException, ExecutionException {
        UserUtils.setUserId("123456");
        CompletableFuture<String> completableFuture = asyncService.executeValueAsync2();
        String s = completableFuture.get();
        return s;
    }

方案2.RequestContextHolder+TaskDecorator

自定義CustomTaskDecorator

/**
 * 線程池修飾類
 */
public class CustomTaskDecorator implements TaskDecorator {
    @Override
    public Runnable decorate(Runnable runnable) {
        // 獲取主線程中的請求信息(我們的用戶信息也放在里面)
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        return () -> {
            try {
                // 將主線程的請求信息,設(shè)置到子線程中
                RequestContextHolder.setRequestAttributes(attributes);
                // 執(zhí)行子線程,這一步不要忘了
                runnable.run();
            } finally {
                // 線程結(jié)束,清空這些信息,否則可能造成內(nèi)存泄漏
                RequestContextHolder.resetRequestAttributes();
            }
        };
    }
}

ExecutorConfig

在原來的基礎(chǔ)上增加 executor.setTaskDecorator(new CustomTaskDecorator());

@Bean(name = "asyncServiceExecutor")
    public Executor asyncServiceExecutor() {
        log.info("start asyncServiceExecutor----------------");
        //ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //使用可視化運行狀態(tài)的線程池
        ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
        //配置核心線程數(shù)
        executor.setCorePoolSize(corePoolSize);
        //配置最大線程數(shù)
        executor.setMaxPoolSize(maxPoolSize);
        //配置隊列大小
        executor.setQueueCapacity(queueCapacity);
        //配置線程池中的線程的名稱前綴
        executor.setThreadNamePrefix(namePrefix);
        // rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時候,如何處理新任務(wù)
        // CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是有調(diào)用者所在的線程來執(zhí)行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //增加線程池修飾類
        executor.setTaskDecorator(new CustomTaskDecorator());
        //增加MDC的線程池修飾類
        //executor.setTaskDecorator(new MDCTaskDecorator());
        //執(zhí)行初始化
        executor.initialize();
        log.info("end asyncServiceExecutor------------");
        return executor;
    }

AsyncServiceImpl

     /**
     * 使用RequestAttributes獲取主線程傳遞的數(shù)據(jù)
     * @return
     * @throws InterruptedException
     */
    @Async("asyncServiceExecutor")
    public CompletableFuture<String> executeValueAsync3() throws InterruptedException {
        log.info("start executeValueAsync");
        System.out.println("異步線程執(zhí)行返回結(jié)果......+");
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        Object userId = attributes.getAttribute("userId", 0);
        log.info("end executeValueAsync");
        return CompletableFuture.completedFuture(userId.toString());
    }

Test2Controller

    /**
     * RequestContextHolder+TaskDecorator的方式
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @GetMapping("/test3")
    public String test3() throws InterruptedException, ExecutionException {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        attributes.setAttribute("userId","123456",0);
        CompletableFuture<String> completableFuture = asyncService.executeValueAsync3();
        String s = completableFuture.get();
        return s;
    }

方案3.MDC+TaskDecorator

自定義MDCTaskDecorator

/**
 * 線程池修飾類
 */
public class MDCTaskDecorator implements TaskDecorator {
    @Override
    public Runnable decorate(Runnable runnable) {
        // 獲取主線程中的請求信息(我們的用戶信息也放在里面)
        String userId = MDC.get("userId");
        Map<String, String> copyOfContextMap = MDC.getCopyOfContextMap();
        System.out.println(copyOfContextMap);
        return () -> {
            try {
                // 將主線程的請求信息,設(shè)置到子線程中
                MDC.put("userId",userId);
                // 執(zhí)行子線程,這一步不要忘了
                runnable.run();
            } finally {
                // 線程結(jié)束,清空這些信息,否則可能造成內(nèi)存泄漏
                MDC.clear();
            }
        };
    }
}

ExecutorConfig

在原來的基礎(chǔ)上增加 executor.setTaskDecorator(new MDCTaskDecorator());

@Bean(name = "asyncServiceExecutor")
    public Executor asyncServiceExecutor() {
        log.info("start asyncServiceExecutor----------------");
        //ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //使用可視化運行狀態(tài)的線程池
        ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
        //配置核心線程數(shù)
        executor.setCorePoolSize(corePoolSize);
        //配置最大線程數(shù)
        executor.setMaxPoolSize(maxPoolSize);
        //配置隊列大小
        executor.setQueueCapacity(queueCapacity);
        //配置線程池中的線程的名稱前綴
        executor.setThreadNamePrefix(namePrefix);
        // rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時候,如何處理新任務(wù)
        // CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是有調(diào)用者所在的線程來執(zhí)行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //增加MDC的線程池修飾類
        executor.setTaskDecorator(new MDCTaskDecorator());
        //執(zhí)行初始化
        executor.initialize();
        log.info("end asyncServiceExecutor------------");
        return executor;
    }

AsyncServiceImpl

         /**
     * 使用MDC獲取主線程傳遞的數(shù)據(jù)
     * @return
     * @throws InterruptedException
     */
    @Async("asyncServiceExecutor")
    public CompletableFuture<String> executeValueAsync5() throws InterruptedException {
        log.info("start executeValueAsync");
        System.out.println("異步線程執(zhí)行返回結(jié)果......+");
        log.info("end executeValueAsync");
        return CompletableFuture.completedFuture(MDC.get("userId"));
    }

Test2Controller

     /**
     * 使用MDC+TaskDecorator方式
     * 本質(zhì)也是ThreadLocal+TaskDecorator方式
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @GetMapping("/test5")
    public String test5() throws InterruptedException, ExecutionException {
        MDC.put("userId","123456");
        CompletableFuture<String> completableFuture = asyncService.executeValueAsync5();
        String s = completableFuture.get();
        return s;
    }

方案4.InheritableThreadLocal

用戶工具類 UserInheritableUtils

//**
 *使用InheritableThreadLocal存儲線程之間共享的數(shù)據(jù)變量,如登錄的用戶信息
 */
public class UserInheritableUtils {
    private static  final  InheritableThreadLocal<String> userLocal=new InheritableThreadLocal<>();
 
    public static  String getUserId(){
        return userLocal.get();
    }
    public static void setUserId(String userId){
        userLocal.set(userId);
    }
    public static void clear(){
        userLocal.remove();
    }
}

AsyncServiceImpl

      /**
     * 使用InheritableThreadLocal獲取主線程傳遞的數(shù)據(jù)
     * @return
     * @throws InterruptedException
     */
    @Async("asyncServiceExecutor")
    public CompletableFuture<String> executeValueAsync4() throws InterruptedException {
        log.info("start executeValueAsync");
        System.out.println("異步線程執(zhí)行返回結(jié)果......+");
        log.info("end executeValueAsync");
        return CompletableFuture.completedFuture(UserInheritableUtils.getUserId());
    }

Test2Controller

       /**
     * 使用InheritableThreadLocal方式
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @GetMapping("/test4")
    public String test4(@RequestParam("userId") String userId) throws InterruptedException, ExecutionException {
        UserInheritableUtils.setUserId(userId);
        CompletableFuture<String> completableFuture = asyncService.executeValueAsync4();
        String s = completableFuture.get();
        return s;
    }

方案5.TransmittableThreadLocal

用戶工具類 UserTransmittableUtils

/**
 *使用TransmittableThreadLocal存儲線程之間共享的數(shù)據(jù)變量,如登錄的用戶信息
 */
public class UserTransmittableUtils {
    private static  final TransmittableThreadLocal<String> userLocal=new TransmittableThreadLocal<>();
    public static  String getUserId(){
        return userLocal.get();
    }
    public static void setUserId(String userId){
        userLocal.set(userId);
    }
    public static void clear(){
        userLocal.remove();
    }
}
}

AsyncServiceImpl

   /**
     * 使用TransmittableThreadLocal獲取主線程傳遞的數(shù)據(jù)
     * @return
     * @throws InterruptedException
     */
    @Async("asyncServiceExecutor")
    public CompletableFuture<String> executeValueAsync6() throws InterruptedException {
        log.info("start executeValueAsync");
        System.out.println("異步線程執(zhí)行返回結(jié)果......+");
        log.info("end executeValueAsync");
        return CompletableFuture.completedFuture(UserTransmittableUtils.getUserId());
    }

Test2Controller

   /**
     * 使用TransmittableThreadLocal方式
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @GetMapping("/test6")
    public String test6() throws InterruptedException, ExecutionException {
        UserTransmittableUtils.setUserId("123456");
        CompletableFuture<String> completableFuture = asyncService.executeValueAsync6();
        String s = completableFuture.get();
        return s;
    }

maven依賴

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>transmittable-thread-local</artifactId>
            <version>2.12.1</version>
        </dependency>

方案對比

方案1,方案2,方案3主要是借助TaskDecorator進(jìn)行父子線程之間傳遞數(shù)據(jù)。其中MDC方案主要借鑒于MDC的日志跟蹤的思想來實現(xiàn),關(guān)于MDC相關(guān)的日志跟蹤后續(xù)會學(xué)習(xí)分享

方案4和方案5使用InheritableThreadLocal和TransmittableThreadLocal來實現(xiàn),其中TransmittableThreadLocal是阿里InheritableThreadLocal進(jìn)行優(yōu)化封裝。

本人推薦使用方案5,哈哈。

簡答說一下InheritableThreadLocal

public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1,1,1,
                TimeUnit.MINUTES,new ArrayBlockingQueue<>(1));
        ThreadLocal local = new InheritableThreadLocal();
        local.set(1);
        executor.execute(()->{
            System.out.println("打印1:"+local.get());
        });
        local.set(2);
        System.out.println("打印2:"+local.get());
        executor.execute(()->{
            System.out.println("打印3:"+local.get());
        });
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("打印4:"+local.get());
            }
        }).start();
    }

運行結(jié)果如下

打印2:2
打印1:1
打印3:1
打印4:2

分析: 分析打印3為什么是1,InheritableThreadLocal的繼承性是在new Thread創(chuàng)建子線程時候在構(gòu)造函數(shù)內(nèi)把父線程內(nèi)線程變量拷貝到子線程內(nèi)部的。 為了不在創(chuàng)建新線程耗費資源,我們一般會用線程池,線程池的線程會復(fù)用,那么線程中的ThreadLocal便不對了,可能是舊的,因為線程是舊的。

總結(jié)

上面的的方案你學(xué)會了么

到此這篇關(guān)于SpringBoot父子線程數(shù)據(jù)傳遞的五種方案介紹的文章就介紹到這了,更多相關(guān)SpringBoot數(shù)據(jù)傳遞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java Socket編程(三) 服務(wù)器Sockets

    Java Socket編程(三) 服務(wù)器Sockets

    Java Socket編程(三) 服務(wù)器Sockets...
    2006-12-12
  • JVM內(nèi)存結(jié)構(gòu)劃分實例解析

    JVM內(nèi)存結(jié)構(gòu)劃分實例解析

    這篇文章主要介紹了JVM內(nèi)存結(jié)構(gòu)劃分實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • SpringBoot+阿里云OSS實現(xiàn)在線視頻播放的示例

    SpringBoot+阿里云OSS實現(xiàn)在線視頻播放的示例

    這篇文章主要介紹了SpringBoot+阿里云OSS實現(xiàn)在線視頻播放的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Java使用正則表達(dá)式檢索、替換String中特定字符和正則表達(dá)式的一切

    Java使用正則表達(dá)式檢索、替換String中特定字符和正則表達(dá)式的一切

    這篇文章主要給大家介紹了關(guān)于Java使用正則表達(dá)式檢索、替換String中特定字符和正則表達(dá)式的一切,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • SpringBoot的SPI機(jī)制源碼解析

    SpringBoot的SPI機(jī)制源碼解析

    這篇文章主要為大家介紹了SpringBoot的SPI機(jī)制源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Java+Mysql學(xué)生管理系統(tǒng)源碼

    Java+Mysql學(xué)生管理系統(tǒng)源碼

    這篇文章主要為大家詳細(xì)介紹了Java+Mysql學(xué)生管理系統(tǒng)源碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • java實現(xiàn)獲取用戶的MAC地址

    java實現(xiàn)獲取用戶的MAC地址

    本文給大家匯總介紹了下使用java實現(xiàn)獲取客戶端用戶的MAC地址的方法,當(dāng)然最后一種更全面一些,有需要的小伙伴們可以根據(jù)需求自由選擇。
    2015-10-10
  • Spring-Boot 訪問外部接口的方案總結(jié)

    Spring-Boot 訪問外部接口的方案總結(jié)

    在Spring-Boot項目開發(fā)中,存在著本模塊的代碼需要訪問外面模塊接口,或外部url鏈接的需求,針對這一需求目前存在著三種解決方案,下面將對這三種方案進(jìn)行整理和說明,對Spring-Boot 訪問外部接口方案感興趣的朋友跟隨小編一起看看吧
    2022-12-12
  • 如何使用 Spring Boot 和 Canal 實現(xiàn) MySQL 數(shù)據(jù)庫同步

    如何使用 Spring Boot 和 Canal 實現(xiàn) My

    本文介紹了如何使用SpringBoot和Canal實現(xiàn)MySQL數(shù)據(jù)庫之間的數(shù)據(jù)同步,通過配置主庫、創(chuàng)建Canal用戶、配置CanalServer以及開發(fā)SpringBoot客戶端,實現(xiàn)了將主庫的數(shù)據(jù)實時同步到多個從庫,感興趣的朋友跟隨小編一起看看吧
    2025-02-02
  • MyBatisPlus代碼生成器的使用示例

    MyBatisPlus代碼生成器的使用示例

    本文主要介紹了MyBatisPlus代碼生成器的使用示例,通過 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各個模塊的代碼,感興趣的可以了解一下
    2021-12-12

最新評論

增城市| 桓台县| 清河县| 新乡县| 津南区| 班戈县| 卢氏县| 砚山县| 大冶市| 普安县| 伊通| 确山县| 中江县| 四子王旗| 永登县| 沁源县| 镇赉县| 江门市| 新兴县| 师宗县| 股票| 永定县| 漯河市| 广饶县| 东阿县| 略阳县| 龙井市| 南乐县| 徐州市| 项城市| 舒城县| 竹溪县| 介休市| 曲沃县| 保亭| 玉环县| 肇州县| 平顶山市| 新巴尔虎左旗| 四子王旗| 淮安市|