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

一文搞懂SpringBoot如何利用@Async實現(xiàn)異步調(diào)用

 更新時間:2022年09月08日 14:38:43   作者:老顧聊技術(shù)  
異步調(diào)用幾乎是處理高并發(fā),解決性能問題常用的手段,如何開啟異步調(diào)用?SpringBoot中提供了非常簡單的方式,就是一個注解@Async。今天我們重新認識一下@Async,以及注意事項

前言

異步調(diào)用幾乎是處理高并發(fā),解決性能問題常用的手段,如何開啟異步調(diào)用?SpringBoot中提供了非常簡單的方式,就是一個注解@Async。今天我們重新認識一下@Async,以及注意事項

簡單使用

新建三個作業(yè)任務(wù):

@Service
public class TaskDemo {
    private static Logger logger = LoggerFactory.getLogger(TaskDemo.class);
    public void execute1() {
        logger.info("處理耗時任務(wù)1......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)1......結(jié)束");
    }
    public void execute2() {
        logger.info("處理耗時任務(wù)2......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)2......結(jié)束");
    }
    public void execute3() {
        logger.info("處理耗時任務(wù)3......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)3......結(jié)束");
    }
}

測試代碼:

@RestController
public class TaskController {
    @Autowired
    private TaskDemo taskDemo;

    @GetMapping("/task/test")
    public String testTask() {
        taskDemo.execute1();
        taskDemo.execute2();
        taskDemo.execute3();
        return "ok";
    }
}

執(zhí)行后我們可以發(fā)現(xiàn),上面的代碼是同一個線程的同步執(zhí)行,整體耗時9秒才完成。

異步處理

springboot的異步,是非常簡單的,加2個注解即可

@Service
public class TaskDemo {

    private static Logger logger = LoggerFactory.getLogger(TaskDemo.class);

    @Async
    public void execute1() {
        logger.info("處理耗時任務(wù)1......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)1......結(jié)束");
    }

    @Async
    public void execute2() {
        logger.info("處理耗時任務(wù)2......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)2......結(jié)束");
    }

    @Async
    public void execute3() {
        logger.info("處理耗時任務(wù)3......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)3......結(jié)束");
    }

}
@SpringBootApplication
@EnableAsync
public class DemoApp {
    public static void main(String[] args) {
        SpringApplication.run(DemoApp.class,args);
    }
}

增加了@Async和@EnableAsync兩個注解

從執(zhí)行結(jié)果發(fā)現(xiàn),整個流程用了3秒,以及用了3個線程執(zhí)行。完成了異步調(diào)用

異步回調(diào)

有些場景我們需要知道異步處理的任務(wù)什么時候完成,需要做額外的業(yè)務(wù)處理。如:我們需要在3個任務(wù)都完成后,提示一下給用戶

@Service
public class TaskDemo {

    private static Logger logger = LoggerFactory.getLogger(TaskDemo.class);

    @Async
    public Future<String> execute1() {
        logger.info("處理耗時任務(wù)1......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)1......結(jié)束");

        return new AsyncResult<>("任務(wù)1 ok");
    }

    @Async
    public Future<String> execute2() {
        logger.info("處理耗時任務(wù)2......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)2......結(jié)束");

        return new AsyncResult<>("任務(wù)2 ok");
    }

    @Async
    public Future<String> execute3() {
        logger.info("處理耗時任務(wù)3......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)3......結(jié)束");

        return new AsyncResult<>("任務(wù)3 ok");
    }
}
@RestController
public class TaskController {

    private static Logger logger = LoggerFactory.getLogger(TaskController.class);

    @Autowired
    private TaskDemo taskDemo;

    @GetMapping("/task/test")
    public String testTask() throws InterruptedException {
        Future<String> task1 = taskDemo.execute1();
        Future<String> task2 = taskDemo.execute2();
        Future<String> task3 = taskDemo.execute3();

        while (true){
            if (task1.isDone() && task2.isDone() && task3.isDone()){
                break;
            }
            TimeUnit.SECONDS.sleep(1);
        }

        logger.info(">>>>>>3個任務(wù)都處理完成");
        return "ok";
    }
}

執(zhí)行結(jié)果發(fā)現(xiàn),在請求線程里面給用戶提示了3個任務(wù)都處理完成了。

這段代碼主要改變了什么:

1、把具體任務(wù)返回類型改為了Future類型對象

2、在調(diào)用任務(wù)時,循環(huán)判斷任務(wù)是否處理完

自定義線程池

說到異步處理,一定要考慮到線程池,什么是線程池,小伙伴可自行網(wǎng)補。@Async的線程池定義比較方便,直接上代碼:

@Configuration
public class ThreadPoolConfig {

    @Bean(name = "taskPool01Executor")
    public ThreadPoolTaskExecutor getTaskPool01Executor() {

        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //核心線程數(shù)
        taskExecutor.setCorePoolSize(10);
        //線程池維護線程的最大數(shù)量,只有在緩沖隊列滿了之后才會申請超過核心線程數(shù)的線程
        taskExecutor.setMaxPoolSize(100);
        //緩存隊列
        taskExecutor.setQueueCapacity(50);
        //許的空閑時間,當超過了核心線程出之外的線程在空閑時間到達之后會被銷毀
        taskExecutor.setKeepAliveSeconds(200);
        //異步方法內(nèi)部線程名稱
        taskExecutor.setThreadNamePrefix("TaskPool-01-");
        /**
         * 當線程池的任務(wù)緩存隊列已滿并且線程池中的線程數(shù)目達到maximumPoolSize,如果還有任務(wù)到來就會采取任務(wù)拒絕策略
         * 通常有以下四種策略:
         * ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常。
         * ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù),但是不拋出異常。
         * ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務(wù),然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過程)
         * ThreadPoolExecutor.CallerRunsPolicy:重試添加當前的任務(wù),自動重復(fù)調(diào)用 execute() 方法,直到成功
         */
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);

        taskExecutor.initialize();

        return taskExecutor;
    }

    @Bean(name = "taskPool02Executor")
    public ThreadPoolTaskExecutor getTaskPool02Executor() {

        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //核心線程數(shù)
        taskExecutor.setCorePoolSize(10);
        //線程池維護線程的最大數(shù)量,只有在緩沖隊列滿了之后才會申請超過核心線程數(shù)的線程
        taskExecutor.setMaxPoolSize(100);
        //緩存隊列
        taskExecutor.setQueueCapacity(50);
        //許的空閑時間,當超過了核心線程出之外的線程在空閑時間到達之后會被銷毀
        taskExecutor.setKeepAliveSeconds(200);
        //異步方法內(nèi)部線程名稱
        taskExecutor.setThreadNamePrefix("TaskPool-02-");
        /**
         * 當線程池的任務(wù)緩存隊列已滿并且線程池中的線程數(shù)目達到maximumPoolSize,如果還有任務(wù)到來就會采取任務(wù)拒絕策略
         * 通常有以下四種策略:
         * ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常。
         * ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù),但是不拋出異常。
         * ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務(wù),然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過程)
         * ThreadPoolExecutor.CallerRunsPolicy:重試添加當前的任務(wù),自動重復(fù)調(diào)用 execute() 方法,直到成功
         */
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);

        taskExecutor.initialize();

        return taskExecutor;
    }

}

定義了2個線程池Bean

@Service
public class TaskDemo {

    private static Logger logger = LoggerFactory.getLogger(TaskDemo.class);

    @Async("taskPool01Executor")
    public Future<String> execute1() {
        logger.info("處理耗時任務(wù)1......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)1......結(jié)束");

        return new AsyncResult<>("任務(wù)1 ok");
    }

    @Async("taskPool01Executor")
    public Future<String> execute2() {
        logger.info("處理耗時任務(wù)2......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)2......結(jié)束");

        return new AsyncResult<>("任務(wù)2 ok");
    }

    @Async("taskPool02Executor")
    public Future<String> execute3() {
        logger.info("處理耗時任務(wù)3......開始");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("處理耗時任務(wù)3......結(jié)束");

        return new AsyncResult<>("任務(wù)3 ok");
    }

}

@Async(“線程池名稱”),指定value使用自己定義的線程池:

執(zhí)行結(jié)果利用了線程池。

注意事項(一定注意)

在使用@Async注解時,很多小伙伴都會發(fā)現(xiàn)異步使用失敗。主要原因是異步方法的定義出了問題。

1、異步方法不能使用static修飾

2、異步類沒有使用@Component注解(或其他注解)導(dǎo)致spring無法掃描到異步類

3、異步方法和調(diào)用異步方法的方法不能在同一個類

4、類中需要使用@Autowired或@Resource等注解自動注入,不能自己手動new對象

5、如果使用SpringBoot框架必須在啟動類中增加@EnableAsync注解?

到此這篇關(guān)于一文搞懂SpringBoot如何利用@Async實現(xiàn)異步調(diào)用的文章就介紹到這了,更多相關(guān)SpringBoot @Async異步調(diào)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java Linkedlist原理及實例詳解

    Java Linkedlist原理及實例詳解

    這篇文章主要介紹了Java Linkedlist原理及實例詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • spring?aop?Pointcut?execution規(guī)則介紹

    spring?aop?Pointcut?execution規(guī)則介紹

    這篇文章主要介紹了spring?aop?Pointcut?execution規(guī)則,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SpringBoot項目攔截器獲取Post方法的請求body實現(xiàn)

    SpringBoot項目攔截器獲取Post方法的請求body實現(xiàn)

    本文主要介紹了SpringBoot項目攔截器獲取Post方法的請求body,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Java中SimpleDateFormat 格式化日期的使用

    Java中SimpleDateFormat 格式化日期的使用

    本文主要介紹了Java中SimpleDateFormat 格式化日期的使用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • SpringBoot指標監(jiān)控功能實現(xiàn)

    SpringBoot指標監(jiān)控功能實現(xiàn)

    這篇文章主要介紹了SpringBoot指標監(jiān)控功能實現(xiàn),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • Activiti進階之組任務(wù)實現(xiàn)示例詳解

    Activiti進階之組任務(wù)實現(xiàn)示例詳解

    這篇文章主要為大家介紹了Activiti進階之組任務(wù)實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • 淺談Spring中幾個PostProcessor的區(qū)別與聯(lián)系

    淺談Spring中幾個PostProcessor的區(qū)別與聯(lián)系

    這篇文章主要介紹了淺談Spring中幾個PostProcessor的區(qū)別與聯(lián)系,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java利用數(shù)組隨機抽取幸運觀眾如何實現(xiàn)

    Java利用數(shù)組隨機抽取幸運觀眾如何實現(xiàn)

    這篇文章主要介紹了Java利用數(shù)組隨機抽取幸運觀眾如何實現(xiàn),需要的朋友可以參考下
    2014-02-02
  • springboot中json對象中對Long類型和String類型相互轉(zhuǎn)換

    springboot中json對象中對Long類型和String類型相互轉(zhuǎn)換

    與前端聯(lián)調(diào)接口時,后端一些字段設(shè)計為Long類型,這樣就有可能導(dǎo)致前端缺失精度,這時候我們就需要將Long類型返回給前端時做數(shù)據(jù)類型轉(zhuǎn)換,本文主要介紹了springboot中json對象中對Long類型和String類型相互轉(zhuǎn)換,感興趣的可以了解一下
    2023-11-11
  • java中DelayQueue實例用法詳解

    java中DelayQueue實例用法詳解

    在本篇內(nèi)容里小編給大家分享的是一篇關(guān)于java中DelayQueue實例用法詳解內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)下。
    2021-01-01

最新評論

乌鲁木齐县| 祁门县| 济源市| 伊宁县| 东安县| 革吉县| 永年县| 汕尾市| 炉霍县| 黄山市| 绍兴县| 怀宁县| 新闻| 昌江| 中阳县| 新安县| 禹城市| 五莲县| 淮南市| 固镇县| 锡林郭勒盟| 靖西县| 龙南县| 普兰店市| 洪洞县| 运城市| 三江| 麻江县| 邹平县| 大同市| 嵩明县| 铅山县| 奈曼旗| 吉隆县| 平度市| 合江县| 磐石市| 西峡县| 吴忠市| 内乡县| 荔浦县|