欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的異步與線程池解讀

 更新時(shí)間:2022年11月22日 14:56:16   作者:最好束手就擒  
這篇文章主要介紹了Java中的異步與線程池,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

初始化線程的4種方式

1.繼承Thread

	Thread01 thread01 = new Thread01();
	thread01.start();

    public static  class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("當(dāng)前線程:"+Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("運(yùn)行結(jié)果:"+i);
        }
    }

2.實(shí)現(xiàn)Runnable 接口

	Runnable01 runnable01 = new Runnable01();
    new Thread(runnable01).start();

    public static class Runnable01 implements Runnable{
        @Override
        public void run() {
            System.out.println("當(dāng)前線程:"+Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("運(yùn)行結(jié)果:"+i);
        }
    }

3.實(shí)現(xiàn)Callable 接口+ FutureTask (可以拿到返回結(jié)果,可以處理異常)

    Callabel01 callabel01 = new Callabel01();

    FutureTask<Integer> integerFutureTask = new FutureTask<>(callabel01);
    //阻塞等待整個(gè)線程執(zhí)行完成,獲取返回結(jié)果
    Integer integer = integerFutureTask.get();
    new Thread(integerFutureTask).start();

    public static class Callabel01 implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("當(dāng)前線程:"+Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("運(yùn)行結(jié)果:"+i);
            return i;
        }
    }

在業(yè)務(wù)代碼里面不建議使用以上三種啟動線程的方式 

4.線程池

應(yīng)該將所有的多線程異步任務(wù)都交給線程池執(zhí)行,進(jìn)行有效的資源控制

//當(dāng)前系統(tǒng)中池只有一兩個(gè),每一個(gè)異步任務(wù)直接提交給線程池,讓他自己去執(zhí)行
ExecutorService service = Executors.newFixedThreadPool(10);
//執(zhí)行
service.execute(new Runnable01());

區(qū)別

1/2兩種方式都不能獲取返回值

1/2/3都不能達(dá)到資源控制的效果

只有4能控制資源,系統(tǒng)性能是穩(wěn)定的

創(chuàng)建線程池(ExecutorService)

1.Executors 工具類創(chuàng)建

//當(dāng)前系統(tǒng)中池只有一兩個(gè),每一個(gè)異步任務(wù)直接提交給線程池,讓他自己去執(zhí)行
ExecutorService service = Executors.newFixedThreadPool(10);
//執(zhí)行
service.execute(new Runnable01());

2.原生方法創(chuàng)建線程池

ThreadPoolExecutor需要傳入七大參數(shù)

  • corePoolSize 核心線程數(shù)【一直存在,除非設(shè)置了允許線程超時(shí)的設(shè)置:allowCoreThreadTimeOut】,保留在池中的線??程數(shù),線程池創(chuàng)建后好后就準(zhǔn)備就緒的線程數(shù),就等待異步任務(wù)去執(zhí)行,new 好了 Thread,等待異步任務(wù)
  • maximumPoolSize 池中最大線程數(shù)量,控制資源并發(fā)
  • keepAliveTime 存活時(shí)間,當(dāng)前正在運(yùn)行的線程數(shù)量,大于核心線程數(shù),就會釋放空閑的線程,只要線程空閑大于指定存活時(shí)間,釋放的線程是指最大的線程數(shù)量減去核心線程數(shù),
  • unit 時(shí)間單位
  • BlockingQueue workQueue 阻塞隊(duì)列,如果任務(wù)有很多,就會將目前多的隊(duì)伍放在隊(duì)列里面,只要有空閑的線程,就會去隊(duì)列里面取出新的任務(wù)繼續(xù)執(zhí)行。
  • new LinkedBlockingQueue<>() 默認(rèn)值是Integer的最大值,會導(dǎo)致內(nèi)存不夠,一定要傳入業(yè)務(wù)定制的大小,可以通過壓測得出峰值
  • threadFactory 線程的創(chuàng)建工廠
  • handler 如果隊(duì)列滿了,按照我們指定的拒絕策略拒絕執(zhí)行任務(wù)

3.線程池的運(yùn)行流程 線程池創(chuàng)建

準(zhǔn)備好core 數(shù)量的核心線程,準(zhǔn)備接受任務(wù)新的任務(wù)進(jìn)來,用core 準(zhǔn)備好的空閑線程執(zhí)行。

(1) 、core 滿了,就將再進(jìn)來的任務(wù)放入阻塞隊(duì)列中??臻e的core 就會自己去阻塞隊(duì)列獲取任務(wù)執(zhí)行

(2) 、阻塞隊(duì)列滿了,就直接開新線程執(zhí)行,最大只能開到max 指定的數(shù)量

(3) 、max 都執(zhí)行好了。Max-core 數(shù)量空閑的線程會在keepAliveTime 指定的時(shí)間后自動銷毀。最終保持到core 大小

(4) 、如果線程數(shù)開到了max 的數(shù)量,還有新任務(wù)進(jìn)來,就會使用reject 指定的拒絕策略進(jìn)行處理所有的線程創(chuàng)建都是由指定的factory 創(chuàng)建的。

一個(gè)線程池core 7; max 20 ,queue:50,100 并發(fā)進(jìn)來怎么分配的;先有7 個(gè)能直接得到執(zhí)行,接下來50 個(gè)進(jìn)入隊(duì)列排隊(duì),在多開13 個(gè)繼續(xù)執(zhí)行。

現(xiàn)在70 個(gè)被安排上了。剩下30 個(gè)默認(rèn)拒絕策略。拒絕策略一般是拋棄,如果不想拋棄還要執(zhí)行,可以使用同步的方式執(zhí)行,或者丟棄最老的

4. 四種常見的線程池

  • newCachedThreadPool創(chuàng)建一個(gè)可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。核心線程固定是0,所有都可回收
  • newFixedThreadPool創(chuàng)建一個(gè)固定長線程池,可控制線程最大并發(fā)數(shù),超出的線程會在隊(duì)列中等待。固定大小,核心 = 最大
  • newScheduledThreadPool創(chuàng)建一個(gè)固定長線程池,支持定時(shí)及周期性任務(wù)執(zhí)行。定時(shí)任務(wù)線程池
  • newSingleThreadExecutor創(chuàng)建一個(gè)單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行。后臺從隊(duì)列里面獲取任務(wù) 挨個(gè)執(zhí)行

為什么要使用線程池

降低資源的消耗

通過重復(fù)利用已經(jīng)創(chuàng)建好的線程降低線程的創(chuàng)建和銷毀帶來的損耗

提高響應(yīng)速度

因?yàn)榫€程池中的線程數(shù)沒有超過線程池的最大上限時(shí),有的線程處于等待分配任務(wù)的狀態(tài),當(dāng)任務(wù)來時(shí)無需創(chuàng)建新的線程就能執(zhí)行

提高線程的可管理性

線程池會根據(jù)當(dāng)前系統(tǒng)特點(diǎn)對池內(nèi)的線程進(jìn)行優(yōu)化處理,減少創(chuàng)建和銷毀線程帶來的系統(tǒng)開銷。無限的創(chuàng)建和銷毀線程不僅消耗系統(tǒng)資源,還降低系統(tǒng)的穩(wěn)定性,使用線程池進(jìn)行統(tǒng)一分配

CompletableFuture 異步編排

業(yè)務(wù)場景:

查詢商品詳情頁的邏輯比較復(fù)雜,有些數(shù)據(jù)還需要遠(yuǎn)程調(diào)用,必然需要花費(fèi)更多的時(shí)間

假如商品詳情頁的每個(gè)查詢,需要如下標(biāo)注的時(shí)間才能完成那么,用戶需要5.5s 后才能看到商品詳情頁的內(nèi)容。很顯然是不能接受的。

如果有多個(gè)線程同時(shí)完成這6 步操作,也許只需要1.5s 即可完成響應(yīng)。

CompletableFuture 和FutureTask 同屬于Future 接口的實(shí)現(xiàn)類,都可以獲取線程的執(zhí)行結(jié)果。

1.創(chuàng)建異步對象

1、runXxxx 都是沒有返回結(jié)果的,supplyXxx 都是可以獲取返回結(jié)果的

2、可以傳入自定義的線程池,否則就用默認(rèn)的線程池;

沒有返回結(jié)果的

static ExecutorService service = Executors.newFixedThreadPool(10);
CompletableFuture.runAsync(()->{
     System.out.println("當(dāng)前線程:"+Thread.currentThread().getId());
     int i = 10 / 2;
     System.out.println("運(yùn)行結(jié)果:"+i);
 },service);

有返回結(jié)果的

static ExecutorService service = Executors.newFixedThreadPool(10);
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
	 System.out.println("當(dāng)前線程:" + Thread.currentThread().getId());
	 int i = 10 / 2;
	 System.out.println("運(yùn)行結(jié)果:" + i);
	 return i;
}, service);
	Integer integer = future.get();
	System.out.println("main----end"+integer);

2.計(jì)算完成時(shí)(線程執(zhí)行成功)回調(diào)方法

whenComplete 可以處理正常和異常的計(jì)算結(jié)果,雖然可以得到異常信息,但是不能修改返回?cái)?shù)據(jù)exceptionally 處理異常情況。

可以感知異常并返回默認(rèn)值whenComplete 和whenCompleteAsync 的區(qū)別:

  • whenComplete:是執(zhí)行當(dāng)前任務(wù)的線程執(zhí)行繼續(xù)執(zhí)行whenComplete 的任務(wù)。
  • whenCompleteAsync:是執(zhí)行把whenCompleteAsync 這個(gè)任務(wù)繼續(xù)提交給線程池來進(jìn)行執(zhí)行。

方法不以Async 結(jié)尾,意味著Action 使用相同的線程執(zhí)行,而Async 可能會使用其他線程執(zhí)行(如果是使用相同的線程池,也可能會被同一個(gè)線程選中執(zhí)行)

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main----start");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("當(dāng)前線程:" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("運(yùn)行結(jié)果:" + i);
            return i;
        }, service).whenComplete((res,excption)->{
            System.out.println("異步任務(wù)成功完成:結(jié)果是::::"+res+"異常是:"+excption);
        }).exceptionally(throwable->{
            //可以感知異常,同時(shí)返回?cái)?shù)據(jù)
            return 10;
        });
        Integer integer = future.get();
        System.out.println("main----end"+integer);
    }

3.handle 方法(可對結(jié)果做最后的處理(可處理異常),可改變返回值)

和complete 一樣,可對結(jié)果做最后的處理(可處理異常),可改變返回值。

        /* 方法完成后的處理*/
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("當(dāng)前線程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("運(yùn)行結(jié)果:" + i);
            return i;
        }, service).handle((res,exption)->{
            if (res != null){
                return res*2;
            }
            if (exption != null){
                return 0;
            }
            return 0;
        });

4.線程串行化

  • thenApply 方法:當(dāng)一個(gè)線程依賴另一個(gè)線程時(shí),獲取上一個(gè)任務(wù)返回的結(jié)果,并返回當(dāng)前任務(wù)的返回值。
  • thenAccept 方法:能接收上一步的返回結(jié)果,但是不能改變返回值。
  • thenRun 方法:只要上面的任務(wù)執(zhí)行完成,就開始執(zhí)行thenRun,不能改變返回值帶有Async 默認(rèn)是異步執(zhí)行的。同之前。

以上都要前置任務(wù)成功完成。

Function<? super T,? extends U>

  • T:上一個(gè)任務(wù)返回結(jié)果的類型
  • U:當(dāng)前任務(wù)的返回值類型
  • thenRun 方法:只要上面的任務(wù)執(zhí)行完成,就開始執(zhí)行thenRun,不能改變返回值
static ExecutorService service = Executors.newFixedThreadPool(10);

CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("當(dāng)前線程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("運(yùn)行結(jié)果:" + i);
            return i;
        }, service).thenRunAsync(() -> {
            System.out.println("任務(wù)2啟動了");
        }, service);
  • thenAccept 方法:能接收上一步的返回結(jié)果,但是不能改變返回值。
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("當(dāng)前線程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("運(yùn)行結(jié)果:" + i);
            return i;
        }, service).thenAccept((res)->{
            System.out.println("異步啟動了:"+res);
        });
  • thenApplyAsync 技能接收上一步的結(jié)果,又能改變返回值
 CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("當(dāng)前線程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("運(yùn)行結(jié)果:" + i);
            return i;
        }, service);
        future.thenApplyAsync((res) -> {
            System.out.println("任務(wù)2啟動了:" + res);
            return res + "hello";
        }, service);

        System.out.println("main----end"+future.get());

5.兩任務(wù)組合- 都要完成

兩個(gè)任務(wù)必須都完成,觸發(fā)該任務(wù)。

  • thenCombine:組合兩個(gè)future,獲取兩個(gè)future 的返回結(jié)果,并返回當(dāng)前任務(wù)的返回值
  • thenAcceptBoth:組合兩個(gè)future,獲取兩個(gè)future 任務(wù)的返回結(jié)果,然后處理任務(wù),沒有返回值。
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任務(wù)1線程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任務(wù)1運(yùn)行結(jié)果:" + i);
            return i;
        }, service);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任務(wù)2線程:" + Thread.currentThread().getId());
            System.out.println("任務(wù)2運(yùn)行結(jié)果:");
            return "hello";
        }, service);

        future01.thenAcceptBothAsync(future02, (f1, f2) -> {
            System.out.println("任務(wù)3開始之前的結(jié)果---f1=" + f1 + "f2=" + f2);
        }, service);
  • runAfterBoth:組合兩個(gè)future,不獲取前兩個(gè)的結(jié)果,只需兩個(gè)future 處理完任務(wù)后,處理該任務(wù)。
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任務(wù)1線程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任務(wù)1運(yùn)行結(jié)果:" + i);
            return i;
        }, service);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任務(wù)2線程:" + Thread.currentThread().getId());
            System.out.println("任務(wù)2運(yùn)行結(jié)果:");
            return "hello";
        }, service);

        future01.runAfterBothAsync(future02,()->{
            System.out.println("任務(wù)3開始");
        },service);

6.兩任務(wù)組合- 一個(gè)完成

當(dāng)兩個(gè)任務(wù)中,任意一個(gè)future 任務(wù)完成的時(shí)候,執(zhí)行任務(wù)。

  • applyToEither:兩個(gè)任務(wù)有一個(gè)執(zhí)行完成,獲取它的返回值,處理任務(wù)并自己有新的返回值。
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任務(wù)1線程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任務(wù)1運(yùn)行結(jié)果:" + i);
            return i;
        }, service);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任務(wù)2線程:" + Thread.currentThread().getId());
            System.out.println("任務(wù)2運(yùn)行結(jié)果:");
            return "hello";
        }, service);

        future01.applyToEitherAsync(future02,(t) -> {
            System.out.println("任務(wù)3開始"+t);
            return t.toString() + "niubi";
        }, service);
  • acceptEither:兩個(gè)任務(wù)有一個(gè)執(zhí)行完成,獲取它的返回值,處理任務(wù),自己沒有新的返回值。
 CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任務(wù)1線程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任務(wù)1運(yùn)行結(jié)果:" + i);
            return i;
        }, service);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任務(wù)2線程:" + Thread.currentThread().getId());
            System.out.println("任務(wù)2運(yùn)行結(jié)果:");
            return "hello";
        }, service);

        future01.acceptEitherAsync(future02,(t) -> {
            System.out.println("任務(wù)3開始"+t);
        }, service);
  • runAfterEither:兩個(gè)任務(wù)有一個(gè)執(zhí)行完成,不獲取future 的結(jié)果,處理任務(wù),自己也沒有返回值。
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任務(wù)1線程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任務(wù)1運(yùn)行結(jié)果:" + i);
            return i;
        }, service);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任務(wù)2線程:" + Thread.currentThread().getId());
            System.out.println("任務(wù)2運(yùn)行結(jié)果:");
            return "hello";
        }, service);

        future01.runAfterEitherAsync(future02,() -> {
            System.out.println("任務(wù)3開始");
        }, service);

7.多任務(wù)組合

  • allOf:等待所有任務(wù)完成
CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查詢商品的圖片信息");
            return "hello.png";
        }, service);
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查詢商品的屬性");
            return "黑色+256g";
        }, service);
        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查詢商品的介紹");
            return "華為";
        }, service);

        CompletableFuture<Void> completableFuture = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
        completableFuture.get(); //等待所有結(jié)果完成
  • anyOf:只要有一個(gè)任務(wù)完成

整合SpringBoot

1.添加配置類,新建線程池

package cn.cloud.xmall.product.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Description: ···
 * @author: Freedom
 * @QQ: 1556507698
 * @date:2022/3/21 17:41
 */
@Configuration
public class MyThreadConfig {

    @Bean
    public ThreadPoolExecutor threadPoolExecutor(){
       return new ThreadPoolExecutor(
                20,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
                );
    };
}

2.想要在配置文件中手動的配置參數(shù)

新建一個(gè)配置屬性類

package cn.cloud.xmall.product.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * @Description: ···
 * @author: Freedom
 * @QQ: 1556507698
 * @date:2022/3/21 17:47
 */
@ConfigurationProperties(prefix = "xmall.thread")
@Component  //加入容器
@Data
public class ThreadPollConfigProperties {
    private Integer coreSize;
    private Integer maxSize;
    private Integer keepAliveTime;
}

注:可以在依賴種添加此依賴,在配置文件中就會有我們自己配置屬性的提示

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-configuration-processor</artifactId>
      <optional>true</optional>
  </dependency>

3.配置文件配置屬性

#線程池配置
xmall:
  thread:
    core-size: 20
    max-size: 200
    keep-alive-time: 10

4.使用配置文件中的屬性

@EnableConfigurationProperties(ThreadPollConfigProperties.class),如果配置文件類沒有添加@Component加入容器可以使用這種方式

package cn.cloud.xmall.product.config;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Description: ···
 * @author: Freedom
 * @QQ: 1556507698
 * @date:2022/3/21 17:41
 */
//@EnableConfigurationProperties(ThreadPollConfigProperties.class)
@Configuration
public class MyThreadConfig {

    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPollConfigProperties pool){
       return new ThreadPoolExecutor(
                pool.getCoreSize(),
                pool.getMaxSize(),
                pool.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
                );
    };
}

5.注入線程池

    @Autowired
    private ThreadPoolExecutor executor;

6.異步編排

    @Override
    public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException {

        SkuItemVo skuItemVo = new SkuItemVo();

        //1.使用自己的線程池來新建異步任務(wù)
        CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> {
            //1.查詢基本信息 pms_sku_info
            SkuInfoEntity info = getById(skuId);
            skuItemVo.setInfo(info);
            return info;
        }, executor);

        //2.根據(jù)一號任務(wù)來繼續(xù)調(diào)用
        CompletableFuture<Void> saleAttrFuture = infoFuture.thenAcceptAsync((res) -> {
            //3.獲取當(dāng)前spu的銷售屬性組合
            List<SkuItemSaleAttrVo> saleAttrVos = saleAttrValueService.getSaleAttrsBySpuId(res.getSpuId());
            skuItemVo.setSaleAttr(saleAttrVos);
        }, executor);

        //3.根據(jù)一號任務(wù)來繼續(xù)調(diào)用
        CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync((res) -> {
            //4.獲取Spu的介紹 pms_spu_info_desc
            SpuInfoDescEntity spuInfo = spuInfoDescService.getById(res.getSpuId());
            skuItemVo.setDesc(spuInfo);
        }, executor);

        //4.根據(jù)一號任務(wù)來繼續(xù)調(diào)用
        CompletableFuture<Void> baseAttrFuture = infoFuture.thenAcceptAsync((res) -> {
            //5.獲取spu的規(guī)格參數(shù)信息
            List<SpuItemAttrGroupVo> attrGroups = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
            skuItemVo.setGroupAttrs(attrGroups);
        }, executor);

        //此任務(wù)不需要根據(jù)一號任務(wù)的返回調(diào)用,所以開一個(gè)新線程
        CompletableFuture<Void> imagesFuture = CompletableFuture.runAsync(() -> {
            //2.獲取sku的圖片信息 pms_sku_images
            List<SkuImagesEntity> images = imagesService.getImagesBySkuId(skuId);
            skuItemVo.setImages(images);
        }, executor);

        //等待所有任務(wù)都完成
        //TODO 可以選擇有異常情況下的處理結(jié)果
        CompletableFuture.allOf(saleAttrFuture,descFuture,baseAttrFuture,imagesFuture).get();        

        return skuItemVo;
    }

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

相關(guān)文章

最新評論