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

SpringBoot異步Async使用Future與CompletableFuture區(qū)別小結

 更新時間:2023年06月09日 09:51:46   作者:可樂漢堡cola  
本文主要介紹了SpringBoot異步Async使用Future與CompletableFuture區(qū)別小結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

主要區(qū)別:

  • Future:在執(zhí)行結束后沒法回調,調用get方法會被阻塞;
  • CompletableFuture:在執(zhí)行結束后可通過whenComplete或whenCompleteAsync方法回調,不會阻塞線程,同時也是支持get方法的;

代碼示例

spring boot配置Async,@EnableAsync啟動異步

AsyncConfig

package com.test.config;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@EnableAsync
@Configuration
public class AsyncConfig {
    /**
     * 異步任務自定義線程池
     */
    @Bean(name="taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(50);
        executor.setMaxPoolSize(500);
        executor.setQueueCapacity(300);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("自定義線程-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        return executor;
    }
}

1.Future測試:

主線程等待各個異步執(zhí)行的線程返回的結果來做下一步操作,則必須阻塞在future.get()的地方等待結果返回,這時候又變成同步了。適用于需要等異步結果的場景。

FutureService

package com.test.service;
import java.util.concurrent.Future;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
@Service
public class FutureService {
    @Async
    public Future<String> futureTest1(){
        System.out.println(Thread.currentThread().getName()+"進行任務futureTest1...");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"任務futureTest1完成");
        return new AsyncResult<String>("這是任務futureTest1返回結果");
    }
    @Async
    public Future<String> futureTest2(){
        System.out.println(Thread.currentThread().getName()+"進行任務futureTest2...");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"任務futureTest2完成");
        return new AsyncResult<String>("這是任務futureTest2返回結果");
    }
}

FutureController

package com.test.controller;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.test.service.FutureService;
@RestController
@RequestMapping("/future")
public class FutureController {
    @Autowired
    private FutureService futureService;
    //超時時間
      public static final long timeout = 30;
    @RequestMapping(value = "futureTest", method = RequestMethod.GET)
    public String futureTest() {
        // 開始時間戳
        long beginTime = System.currentTimeMillis();
        Future<String> result1 = futureService.futureTest1();
        Future<String> result2 = futureService.futureTest2();
        //添加結果集,30秒超時
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            String str1 = result1.get(timeout, TimeUnit.SECONDS);
            System.out.println(str1);
            String str2 = result2.get(timeout, TimeUnit.SECONDS);
            System.out.println(str2);
            map.put("result1", str1);
            map.put("result2", str2);
            //這里需要等get()完成后才會執(zhí)行,因為get()方法會阻塞
            System.out.println("map集合: "+map.size());
            System.out.println("回調后的任務: "+Thread.currentThread().getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("耗時: "+(System.currentTimeMillis() - beginTime));
        return "success";
    }
}

 打印結果

自定義線程-1進行任務futureTest1...
自定義線程-2進行任務futureTest2...
自定義線程-1任務futureTest1完成
這是任務futureTest1返回結果
自定義線程-2任務futureTest2完成
這是任務futureTest2返回結果
map集合: 2
回調后的任務: http-nio-8082-exec-1
耗時: 5068

大家可以看到,這時候map集合里面是有值的,主線程http-nio-8082-exec-1是在異步執(zhí)行完才執(zhí)行的,因為get方法是會阻塞線程的。耗時5秒是以異步中耗時最長的方法為準,因為要等耗時最長的方法執(zhí)行完,才能合并。

2.CompletableFuture測試:

實現(xiàn)了Future和CompletionStage接口,保留了Future的優(yōu)點,并且彌補了其不足。即異步的任務完成后,需要用其結果繼續(xù)操作時,無需等待。適用于不需要等異步結果的場景。

CompletableFutureService

package com.test.service;
import java.util.concurrent.CompletableFuture;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class CompletableFutureService {
    @Async
    public CompletableFuture<String> completableFuture1(){
        System.out.println(Thread.currentThread().getName()+"進行任務completableFuture1...");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"任務completableFuture1完成");
        return CompletableFuture.completedFuture("這是任務completableFuture1返回結果");
    }
    @Async
    public CompletableFuture<String> completableFuture2(){
        System.out.println(Thread.currentThread().getName()+"進行任務completableFuture2...");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"任務completableFuture2完成");
        return CompletableFuture.completedFuture("這是任務completableFuture2返回結果");
    }
}

CompletableFutureController

package com.test.controller;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.test.service.CompletableFutureService;
@RestController
@RequestMapping("/completable")
public class CompletableFutureController {
    @Autowired
    private CompletableFutureService completableFutureService;
    @RequestMapping(value = "completableFutureTest", method = RequestMethod.GET)
    public String CompletableFutureTest() {
        // 開始時間戳
        long beginTime = System.currentTimeMillis();
        CompletableFuture<String> result1 = completableFutureService.completableFuture1();
        CompletableFuture<String> result2 = completableFutureService.completableFuture2();
        //添加結果集,30秒超時
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            result1.whenComplete((r, t)->{
                System.out.println(r+Thread.currentThread().getName());
                map.put("result1", r);
            });
            result2.whenComplete((r, t)->{
                System.out.println(r+Thread.currentThread().getName());
                map.put("result2", r);
            });
            //這里不用等前面的結果集,會異步先執(zhí)行
            System.out.println("map集合: "+map.size());
            System.out.println("回調后的任務: "+Thread.currentThread().getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("耗時: "+(System.currentTimeMillis() - beginTime));
        return "success";
    }
}

打印結果

map集合: 0
回調后的任務: http-nio-8082-exec-1
耗時: 33
自定義線程-1進行任務completableFuture1...
自定義線程-2進行任務completableFuture2...
自定義線程-1任務completableFuture1完成
這是任務completableFuture1返回結果自定義線程-1
自定義線程-2任務completableFuture2完成
這是任務completableFuture2返回結果自定義線程-2

大家可以看到,這時候map集合里面是空的,主線程http-nio-8082-exec-1是在異步之前打印的,說明使用whenComplete是異步的,不會阻塞線程的。耗時33毫秒不用等異步執(zhí)行完就能打印。

這里簡單說下whenComplete和whenCompleteAsync的區(qū)別:

whenComplete:執(zhí)行完當前任務的線程,繼續(xù)執(zhí)行 whenComplete 的任務。
whenCompleteAsync: 執(zhí)行完當前任務的線程,把whenCompleteAsync 的任務繼續(xù)提交給線程池來執(zhí)行。(可能開啟新的線程)

把前面的改成whenCompleteAsync測試一下

result1.whenCompleteAsync((r, t)->{
                System.out.println(r+Thread.currentThread().getName());
                map.put("result1", r);
            });
            result2.whenCompleteAsync((r, t)->{
                System.out.println(r+Thread.currentThread().getName());
                map.put("result2", r);
            });

打印結果

map集合: 0
回調后的任務: http-nio-8082-exec-1
耗時: 33
自定義線程-1進行任務completableFuture1...
自定義線程-2進行任務completableFuture2...
自定義線程-1任務completableFuture1完成
這是任務completableFuture1返回結果Thread-4
自定義線程-2任務completableFuture2完成
這是任務completableFuture2返回結果Thread-5

區(qū)別的地方在于Thread-4和Thread-5,這是新開的線程,不是線程池中的線程了。

總結:

Future與CompletableFuture使用場景不一樣,都支持get方法,如果異步執(zhí)行完后需要同步,使用Future,反之,如果異步執(zhí)行完后,不需要等待,直接異步操作,那么使用CompletableFuture。

到此這篇關于SpringBoot異步Async使用Future與CompletableFuture區(qū)別小結的文章就介紹到這了,更多相關SpringBoot Future CompletableFuture內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java中優(yōu)化大量if...else...方法總結

    java中優(yōu)化大量if...else...方法總結

    在我們平時的開發(fā)過程中,經(jīng)常可能會出現(xiàn)大量If else的場景,代碼顯的很臃腫,非常不優(yōu)雅,下面這篇文章主要給大家介紹了關于java中優(yōu)化大量if...else...方法的相關資料,需要的朋友可以參考下
    2023-03-03
  • Java通過反射查看類的信息示例

    Java通過反射查看類的信息示例

    這篇文章主要介紹了Java通過反射查看類的信息,結合實例形式詳細分析了java基于反射獲取類信息的相關原理與實現(xiàn)技巧,需要的朋友可以參考下
    2019-07-07
  • 通過源代碼分析Mybatis的功能流程詳解

    通過源代碼分析Mybatis的功能流程詳解

    這篇文章主要介紹了通過源代碼分析Mybatis的功能,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Java中redis的基本類型

    Java中redis的基本類型

    這篇文章主要介紹了Java中redis的基本類型,redis存儲數(shù)據(jù)的基本類型有:字符串類型、散列類型、列表類型、集合類型、有序集合類型,下面我們對其中幾個進行簡單介紹,需要的小伙伴可以參考一下
    2022-03-03
  • 關于Java中的可見性和有序性問題

    關于Java中的可見性和有序性問題

    這篇文章主要介紹了關于Java中的可見性和有序性問題,Java在誕生之初就支持多線程,自然也有針對這三者的技術方案,今天就學習一下Java如何解決其中的可見性和有序性導致的問題,需要的朋友可以參考下
    2023-08-08
  • java ExecutorService使用方法詳解

    java ExecutorService使用方法詳解

    這篇文章主要為大家詳細介紹了java ExecutorService使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • Centos下SpringBoot項目啟動與停止腳本的方法

    Centos下SpringBoot項目啟動與停止腳本的方法

    這篇文章主要介紹了Centos下SpringBoot項目啟動與停止腳本的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • springboot啟動腳本start.sh和停止腳本 stop.sh的詳細教程

    springboot啟動腳本start.sh和停止腳本 stop.sh的詳細教程

    這篇文章主要介紹了springboot啟動腳本start.sh和停止腳本 stop.sh的詳細教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Java新手環(huán)境搭建 Tomcat安裝配置教程

    Java新手環(huán)境搭建 Tomcat安裝配置教程

    這篇文章主要為大家詳細介紹了Java新手環(huán)境搭建的相關資料,Tomcat安裝配置教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • httpclient evict操作源碼解讀

    httpclient evict操作源碼解讀

    這篇文章主要為大家介紹了httpclient evict操作源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10

最新評論