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

如何解決異步任務(wù)上下文丟失問題

 更新時間:2024年09月18日 10:48:18   作者:勿語&  
在多線程編程中,異步任務(wù)可能會導(dǎo)致上下文信息丟失,為了解決這個問題,可以在執(zhí)行異步任務(wù)前,通過自定義TaskDecorator拷貝主線程的上下文至子線程,這樣可以確保上下文在異步執(zhí)行過程中得以保留,將定制的TaskDecorator設(shè)置至線程池,可以有效地解決上下文丟失問題

解決異步任務(wù)上下文丟失問題

  • 上下文丟失主要是因為主線程和子線程的上下文不能共享。
  • 可以通過執(zhí)行異步任務(wù)之前,將主線程上的上下文信息拷貝到子線程上。

自定義TaskDecorator 來拷貝主線程上的上下文信息到子線程,然后將自定義的 TaskDecorator實現(xiàn)類 設(shè)置到線程池上。

@Configuration
public class ThreadPoolConfig {

    @Bean(name = "customizeTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
        ThreadPoolTaskExecutor poolExecutor = new ThreadPoolTaskExecutor();
        // 核心線程數(shù)=cpu核心數(shù)+1
        poolExecutor.setCorePoolSize(5);
        // 最大線程數(shù)=cpu核心數(shù)*2
        poolExecutor.setMaxPoolSize(8);
        // 設(shè)置任務(wù)裝飾器
        poolExecutor.setTaskDecorator(taskDecorator());
        // 任務(wù)被拒絕后,交給調(diào)用線程執(zhí)行
        poolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return poolExecutor;
    }

    @Bean
    public TaskDecorator taskDecorator(){
        return new TaskDecorator() {
            @Override
            public Runnable decorate(Runnable runnable) {
                RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
                return ()->{
                    try {
                        RequestContextHolder.setRequestAttributes(requestAttributes);
                        runnable.run();
                    }finally {
                        RequestContextHolder.resetRequestAttributes();
                    }
                };
            }
        };
    }
}

Fegin異步情況丟失上下文問題

在微服務(wù)的開發(fā)中,我們經(jīng)常需要服務(wù)之間的調(diào)用,并且為了提高效率使用異步的方式進行服務(wù)之間的調(diào)用,在這種異步的調(diào)用情況下會有一個嚴(yán)重的問題,丟失上文下

通過以上圖片可以看出異步丟失上下文的原因是不在同一個線程,所有數(shù)據(jù)不能共享,Wie了解決這個問題,我們就需要把之前線程的請求頭上下文,在次存放到其他線程的請求頭上下文就行,具體實現(xiàn)如下:

案例:feign異步獲取訂單明細(xì)的案例代碼

/**
     * 獲取訂單明細(xì)的vo
     * @return
     */
    @Override
    public OrderConfirmVo orderConfirm() {
        MemberResponseVo member = OrderInterceptor.threadLocal.get();
 
        OrderConfirmVo orderConfirmVo = new OrderConfirmVo();
        System.out.println("主線程:"+ Thread.currentThread().getId());
        //獲取主線程的請求頭信息
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
 
        //考慮到效率問題  使用異步編排
        CompletableFuture<Void> getAddress = CompletableFuture.runAsync(() -> {
            //子線程中設(shè)置添加主線程的請求頭信息  信息共享  否則遠(yuǎn)程調(diào)用異步處理丟失請求頭信息
            RequestContextHolder.setRequestAttributes(requestAttributes);
            System.out.println("address:"+ Thread.currentThread().getId());
            //遠(yuǎn)程獲取地址信息
            List<MemberAddressVo> address = memberFeignService.getAddress(member.getId());
            orderConfirmVo.setAddress(address);
        }, executor);
 
 
        CompletableFuture<Void> getItem = CompletableFuture.runAsync(() -> {
            //子線程中設(shè)置添加主線程的請求頭信息  信息共享  否則遠(yuǎn)程調(diào)用異步處理丟失請求頭信息
            RequestContextHolder.setRequestAttributes(requestAttributes);
            System.out.println("item:"+ Thread.currentThread().getId());
            //遠(yuǎn)程獲取購物項
            List<OrderItemVo> currentUserCartItems = cartFeignService.getCurrentUserCartItems();
            orderConfirmVo.setItems(currentUserCartItems);
        }, executor).thenRunAsync(()->{
            List<OrderItemVo> items = orderConfirmVo.getItems();
            //獲取所有商品的id
            List<String> collect = items.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
            List<Long> skuIds = collect.stream().map(item -> {
                return Long.parseLong(item);
            }).collect(Collectors.toList());
            R<List<SkuHasStockVo>> skusHasStock = wmsFeignService.getSkusHasStock(skuIds);
            List<SkuHasStockVo> data = skusHasStock.getData(new TypeReference<List<SkuHasStockVo>>() {
            });
            if(data!= null){
                Map<Long, Boolean> collect1 = data.stream().collect(Collectors.toMap(SkuHasStockVo::getSkuId, SkuHasStockVo::getHasStock));
                orderConfirmVo.setStocks(collect1);
            }
        },executor);
 
        //異步編排完成之后執(zhí)行后續(xù)操作
        try {
            CompletableFuture.allOf(getAddress,getItem).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
 
 
        orderConfirmVo.setIntegration(member.getIntegration());
 
        orderConfirmVo.setPayPrice(orderConfirmVo.getPayPrice());
        orderConfirmVo.setTotal(orderConfirmVo.getTotal());
        //TODO 放重處理  生成token令牌儲存在redis
        String token = UUID.randomUUID().toString().replace("-", "");
        orderConfirmVo.setOrderToken(token);
        redisTemplate.opsForValue().set(OrderConstant.ORDER_TOKEN+member.getId(),token);
 
        return orderConfirmVo;
    }

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java檢測死鎖案例

    Java檢測死鎖案例

    這篇文章主要介紹了Java檢測死鎖案例,本文列舉了導(dǎo)致死鎖的程序,通過使用jconsole工具進行檢測等,講述了避免死鎖的方法,需要的朋友可以參考下
    2021-07-07
  • IDEA巧用Postfix Completion讓碼速起飛(小技巧)

    IDEA巧用Postfix Completion讓碼速起飛(小技巧)

    這篇文章主要介紹了IDEA巧用Postfix Completion讓碼速起飛,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Java將文件夾保留目錄打包為 ZIP 壓縮包并下載的教程詳解

    Java將文件夾保留目錄打包為 ZIP 壓縮包并下載的教程詳解

    這篇文章主要介紹了Java將文件夾保留目錄打包為 ZIP 壓縮包并下載的教程詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Spring boot使用多線程過程步驟解析

    Spring boot使用多線程過程步驟解析

    這篇文章主要介紹了Spring boot使用多線程過程步驟解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • 使用Java實現(xiàn)壓縮圖片,視頻和音頻

    使用Java實現(xiàn)壓縮圖片,視頻和音頻

    在?Java?中,要實現(xiàn)視頻壓縮通常需要使用外部的庫或工具,下面就跟隨小編一起來看看如何利用這些庫實現(xiàn)壓縮圖片,視頻和音頻功能吧
    2024-03-03
  • Java微信小程序醫(yī)院掛號系統(tǒng)

    Java微信小程序醫(yī)院掛號系統(tǒng)

    這篇文章主要介紹了基于Java微信小程序醫(yī)院掛號系統(tǒng),可以實現(xiàn)遠(yuǎn)程處理事務(wù),遠(yuǎn)程提交工作和隨時追蹤工作的狀態(tài),文中提供了解決思路和部分實現(xiàn)代碼,需要的朋友可以參考下
    2023-03-03
  • Java中通過三級緩存解決Spring循環(huán)依賴詳解

    Java中通過三級緩存解決Spring循環(huán)依賴詳解

    這篇文章主要介紹了Java中通過三級緩存解決Spring循環(huán)依賴詳解,當(dāng)出現(xiàn)兩個或多個 Bean 在初始化時相互依賴的情況時,Spring Boot 會將其中一個 Bean 提前暴露出來,以便其他 Bean 能夠在初始化時正確地引用它,這一策略能有效避免循環(huán)依賴導(dǎo)致的問題,需要的朋友可以參考下
    2023-09-09
  • Spring boot 配置多個redis的方法示例

    Spring boot 配置多個redis的方法示例

    這篇文章主要介紹了Spring boot 配置多個redis的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 使用jdbcTemplate查詢返回自定義對象集合代碼示例

    使用jdbcTemplate查詢返回自定義對象集合代碼示例

    這篇文章主要介紹了使用jdbcTemplate查詢返回自定義對象集合代碼示例,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • 詳解java安全編碼指南之可見性和原子性

    詳解java安全編碼指南之可見性和原子性

    java類中會定義很多變量,有類變量也有實例變量,這些變量在訪問的過程中,會遇到一些可見性和原子性的問題。這里我們來詳細(xì)了解一下怎么避免這些問題。
    2021-06-06

最新評論

博罗县| 营口市| 盐津县| 洞口县| 西乡县| 民丰县| 塔河县| 五台县| 德惠市| 平利县| 平远县| 砚山县| 获嘉县| 东宁县| 关岭| 衡山县| 扶风县| 颍上县| 绵竹市| 洛扎县| 大同县| 清苑县| 廊坊市| 三台县| 晋宁县| 宣武区| 韶关市| 辽中县| 密山市| 友谊县| 天镇县| 孟州市| 正安县| 寿光市| 巨鹿县| 舒兰市| 长阳| 怀远县| 从江县| 高唐县| 温泉县|