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

SpringBoot實(shí)現(xiàn)定時(shí)任務(wù)和異步調(diào)用

 更新時(shí)間:2019年04月26日 11:17:09   作者:葉落自飄零  
這篇文章主要為大家詳細(xì)介紹了SpringBoot實(shí)現(xiàn)定時(shí)任務(wù)和異步調(diào)用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了SpringBoot實(shí)現(xiàn)定時(shí)任務(wù)和異步調(diào)用的具體代碼,供大家參考,具體內(nèi)容如下

環(huán)境:

jdk1.8;spring boot2.0.2;Maven3.3

摘要說明:

定時(shí)任務(wù):定時(shí)任務(wù)是業(yè)務(wù)場景中經(jīng)常出現(xiàn)的一種情況如:定時(shí)發(fā)送郵件,短信、定時(shí)統(tǒng)計(jì)監(jiān)控?cái)?shù)據(jù)、定時(shí)對(duì)賬等

異步調(diào)用:一個(gè)都買流程可能包括下單、發(fā)貨通知、短信推送、消息推送等,其實(shí)除了下單這個(gè)主要程序是主程序,其他子程序可以同時(shí)進(jìn)行且不影響主程序的運(yùn)行,這個(gè)時(shí)候就可以使用異步調(diào)用來調(diào)用這些子程序;

步驟:

1.定時(shí)任務(wù)

a.在spring boot主類上使用注解@EnableScheduling啟動(dòng)定時(shí)任務(wù):

package com.example.demo;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
 
//啟動(dòng)定時(shí)任務(wù)
@EnableScheduling
@SpringBootApplication
public class DemoApplication {
 
 public static void main(String[] args) {
 SpringApplication.run(DemoApplication.class, args);
 }
}

b.實(shí)現(xiàn)定時(shí)任務(wù)(使用@Component注解來標(biāo)注組件)

 /**
 * @模塊名:demo
 * @包名:com.example.demo.test1.component
 * @描述:SchedulingComponent.java
 * @版本:1.0
 * @創(chuàng)建人:cc
 * @創(chuàng)建時(shí)間:2018年9月29日上午10:19:37
 */
 
package com.example.demo.test1.component;
 
import java.util.Date;
 
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
 
/**
 * @模塊名:demo
 * @包名:com.example.demo.test1.component @類名稱: SchedulingComponent
 * @類描述:【類描述】用于測試定時(shí)任務(wù) @版本:1.0
 * @創(chuàng)建人:cc
 * @創(chuàng)建時(shí)間:2018年9月29日上午10:19:37
 */
@Component
public class SchedulingComponent {
 
 /**
 * 
 * @方法名:testScheduling1
 * @方法描述【方法功能描述】測試定時(shí)任務(wù),沒三秒執(zhí)行一次
 * @修改描述【修改描述】
 * @版本:1.0
 * @創(chuàng)建人:cc
 * @創(chuàng)建時(shí)間:2018年9月29日 上午10:26:20
 * @修改人:cc
 * @修改時(shí)間:2018年9月29日 上午10:26:20
 */
 @Scheduled(fixedRate = 3000)
 public void testScheduling1() {
 
 System.out.println("執(zhí)行時(shí)間為"+new Date()+"執(zhí)行testScheduling1");
 }
}
@Scheduled注解和之前spring使用xml配置定時(shí)任務(wù)類似:

@Scheduled(fixedRate = 5000) :上一次開始執(zhí)行時(shí)間點(diǎn)之后5秒再執(zhí)行
@Scheduled(fixedDelay = 5000) :上一次執(zhí)行完畢時(shí)間點(diǎn)之后5秒再執(zhí)行
@Scheduled(initialDelay=1000, fixedRate=5000) :第一次延遲1秒后執(zhí)行,之后按fixedRate的規(guī)則每5秒執(zhí)行一次
@Scheduled(cron="*/5 * * * * *") :通過cron表達(dá)式定義規(guī)則

c.上述方法寫好后啟動(dòng)服務(wù)看下控制臺(tái)結(jié)果:

2.異步調(diào)用

a.首先在spring boot主類上使用注解@EnableAsync啟動(dòng)異步調(diào)用

package com.example.demo;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
 
//啟動(dòng)異步調(diào)用
@EnableAsync
@SpringBootApplication
public class DemoApplication {
 
 public static void main(String[] args) {
 SpringApplication.run(DemoApplication.class, args);
 }
}

b.sping boot異步調(diào)用很簡單,只需使用@Async注解標(biāo)明方法(接口方法)異步

package com.example.demo.test1.component;
 
public interface TaskComponent {
 void test1() throws Exception;
 
 void test2() throws Exception;
 
 void test3() throws Exception;
}
package com.example.demo.test1.component.impl;
 
import java.util.Random;
 
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
 
import com.example.demo.test1.component.TaskComponent;
 
@Component
public class TaskComponentImpl implements TaskComponent {
 public static Random random = new Random();
 
 @Override
 @Async
 public void test1() throws InterruptedException {
 System.out.println("開始做任務(wù)一");
 long start = System.currentTimeMillis();
 Thread.sleep(random.nextInt(10000));
 long end = System.currentTimeMillis();
 System.out.println("完成任務(wù)一,耗時(shí):" + (end - start) + "毫秒");
 
 }
 
 @Override
 @Async
 public void test2() throws InterruptedException {
 System.out.println("開始做任務(wù)二");
 long start = System.currentTimeMillis();
 Thread.sleep(random.nextInt(10000));
 long end = System.currentTimeMillis();
 System.out.println("完成任務(wù)二,耗時(shí):" + (end - start) + "毫秒");
 
 }
 
 @Override
 @Async
 public void test3() throws InterruptedException {
 System.out.println("開始做任務(wù)三");
 long start = System.currentTimeMillis();
 Thread.sleep(random.nextInt(10000));
 long end = System.currentTimeMillis();
 System.out.println("完成任務(wù)三,耗時(shí):" + (end - start) + "毫秒");
 
 }
 
}

c.使用測試類進(jìn)行測試:

package com.example.demo;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
 
import com.example.demo.test1.component.TaskComponent;
 
@RunWith(SpringRunner.class)
// 引入SpringBootTest并生成隨機(jī)接口
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class AsyncTest {
 
 // 注入隨機(jī)接口
 @LocalServerPort
 private int port;
 
 @Autowired
 private TaskComponent taskComponent;
 
 @Test
 public void testTask() {
 try {
 taskComponent.test1();
 taskComponent.test2();
 taskComponent.test3();
 System.out.println("執(zhí)行主線程");
 // 主線程休眠10秒等待上述異步方法執(zhí)行
 Thread.sleep(10000);
 }
 catch (Exception e) {
 System.out.println(e);
 }
 
 }
}

執(zhí)行結(jié)果如下;可以看出三個(gè)異步方法互不影響,且不影響主線程的運(yùn)行

執(zhí)行主線程
開始做任務(wù)一
開始做任務(wù)二
開始做任務(wù)三
完成任務(wù)一,耗時(shí):1401毫秒
完成任務(wù)二,耗時(shí):4284毫秒
完成任務(wù)三,耗時(shí):5068毫秒

d.對(duì)于這些異步執(zhí)行的調(diào)用往往會(huì)給我們帶來思考是不是異步調(diào)用越多越好,答案當(dāng)然是否;所以在這里引入線程池來進(jìn)行異步調(diào)用控制:

在spring boot主類上標(biāo)注線程池:

package com.example.demo;
 
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 
//啟動(dòng)定時(shí)任務(wù)
 
@EnableScheduling
@SpringBootApplication
public class DemoApplication {
 
 public static void main(String[] args) {
 SpringApplication.run(DemoApplication.class, args);
 }
 
 // 啟動(dòng)異步調(diào)用
 @EnableAsync
 @Configuration
 class TaskPoolConfig {
 // 核心線程數(shù)(setCorePoolSize)10:線程池創(chuàng)建時(shí)候初始化的線程數(shù)
 // 最大線程數(shù)(setMaxPoolSize)20:線程池最大的線程數(shù),只有在緩沖隊(duì)列滿了之后才會(huì)申請超過核心線程數(shù)的線程
 // 緩沖隊(duì)列(setQueueCapacity)200:用來緩沖執(zhí)行任務(wù)的隊(duì)列
 // 允許線程的空閑時(shí)間(setKeepAliveSeconds)60秒:當(dāng)超過了核心線程出之外的線程在空閑時(shí)間到達(dá)之后會(huì)被銷毀
 // 線程池名的前綴(setThreadNamePrefix):設(shè)置好了之后可以方便我們定位處理任務(wù)所在的線程池
 // 線程池對(duì)拒絕任務(wù)的處理策略(setRejectedExecutionHandler):這里采用了CallerRunsPolicy策略,當(dāng)線程池沒有處理能力的時(shí)候,該策略會(huì)直接在 execute
 // 方法的調(diào)用線程中運(yùn)行被拒絕的任務(wù)(setWaitForTasksToCompleteOnShutdown);如果執(zhí)行程序已關(guān)閉,則會(huì)丟棄該任務(wù)
 // setWaitForTasksToCompleteOnShutdown(true)該方法就是這里的關(guān)鍵,用來設(shè)置線程池關(guān)閉的時(shí)候等待所有任務(wù)都完成再繼續(xù)銷毀其他的Bean,這樣這些異步任務(wù)的銷毀就會(huì)先于Redis線程池的銷毀。
 // 同時(shí),這里還設(shè)置了setAwaitTerminationSeconds(60),該方法用來設(shè)置線程池中任務(wù)的等待時(shí)間,如果超過這個(gè)時(shí)候還沒有銷毀就強(qiáng)制銷毀,以確保應(yīng)用最后能夠被關(guān)閉,而不是阻塞住。
 @Bean("taskExecutor")
 public Executor taskExecutor() {
 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
 executor.setCorePoolSize(10);
 executor.setMaxPoolSize(20);
 executor.setQueueCapacity(200);
 executor.setKeepAliveSeconds(60);
 executor.setThreadNamePrefix("taskExecutor-");
 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
 executor.setWaitForTasksToCompleteOnShutdown(true);
 executor.setAwaitTerminationSeconds(60);
 return executor;
 }
 }
}

在方法實(shí)現(xiàn)類上使用@Async的同時(shí)標(biāo)注線程池:

package com.example.demo.test1.component.impl;
 
import java.util.Random;
 
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
 
import com.example.demo.test1.component.TaskComponent;
 
@Component
public class TaskComponentImpl implements TaskComponent {
 public static Random random = new Random();
 
 @Override
 @Async("taskExecutor")
 public void test1() throws InterruptedException {
 System.out.println("開始做任務(wù)一");
 long start = System.currentTimeMillis();
 Thread.sleep(random.nextInt(10000));
 long end = System.currentTimeMillis();
 System.out.println("完成任務(wù)一,耗時(shí):" + (end - start) + "毫秒");
 
 }
 
 @Override
 @Async("taskExecutor")
 public void test2() throws InterruptedException {
 System.out.println("開始做任務(wù)二");
 long start = System.currentTimeMillis();
 Thread.sleep(random.nextInt(10000));
 long end = System.currentTimeMillis();
 System.out.println("完成任務(wù)二,耗時(shí):" + (end - start) + "毫秒");
 
 }
 
 @Override
 @Async("taskExecutor")
 public void test3() throws InterruptedException {
 System.out.println("開始做任務(wù)三");
 long start = System.currentTimeMillis();
 Thread.sleep(random.nextInt(10000));
 long end = System.currentTimeMillis();
 System.out.println("完成任務(wù)三,耗時(shí):" + (end - start) + "毫秒");
 
 }
 
}

再次調(diào)用測試來發(fā)現(xiàn)結(jié)果沒什么區(qū)別:

執(zhí)行主線程
開始做任務(wù)一
開始做任務(wù)二
開始做任務(wù)三
完成任務(wù)一,耗時(shí):1117毫秒
完成任務(wù)二,耗時(shí):3964毫秒
完成任務(wù)三,耗時(shí):8886毫秒

接著我們修改線程池線程數(shù)為2:

executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);

再次啟動(dòng)測試類可以看到,同時(shí)執(zhí)行的線程數(shù)為2,只有等待前一個(gè)線程結(jié)束才能執(zhí)行一個(gè)新的線程;

執(zhí)行主線程
開始做任務(wù)一
開始做任務(wù)二
完成任務(wù)二,耗時(shí):620毫秒
開始做任務(wù)三
完成任務(wù)一,耗時(shí):2930毫秒
完成任務(wù)三,耗時(shí):4506毫秒

3.demo地址:鏈接地址

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring Boot中@RequestParam參數(shù)的5種情況說明

    Spring Boot中@RequestParam參數(shù)的5種情況說明

    這篇文章主要介紹了Spring Boot中@RequestParam參數(shù)的5種情況說明,具有很好的參考價(jià)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java處理異常Exception的方法總結(jié)

    java處理異常Exception的方法總結(jié)

    在Java中處理異常并不是一個(gè)簡單的事情,不僅僅初學(xué)者很難理解,即使一些有經(jīng)驗(yàn)的開發(fā)者也需要花費(fèi)很多時(shí)間,本文為大家整理了java處理異常Exception的一些常用方法,希望對(duì)大家有所幫助
    2023-09-09
  • Java long 轉(zhuǎn)成 String的實(shí)現(xiàn)

    Java long 轉(zhuǎn)成 String的實(shí)現(xiàn)

    這篇文章主要介紹了Java long 轉(zhuǎn)成 String的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Java工具jsch.jar實(shí)現(xiàn)上傳下載

    Java工具jsch.jar實(shí)現(xiàn)上傳下載

    這篇文章主要為大家詳細(xì)介紹了Java操作ftp的一款工具,利用jsch.jar針對(duì)sftp的上傳下載工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • IDEA使用SpringAssistant插件創(chuàng)建SpringCloud項(xiàng)目

    IDEA使用SpringAssistant插件創(chuàng)建SpringCloud項(xiàng)目

    IDEA 功能強(qiáng)大,可以用來高效的開發(fā)應(yīng)該程序。它還支持第三方插件、用戶可以根據(jù)需要添加自己喜歡的插件。下面介紹如何使用 IDEA 創(chuàng)建 Spring Cloud 項(xiàng)目
    2021-06-06
  • Java中JSONObject和Map<String,?Object>的轉(zhuǎn)換方法

    Java中JSONObject和Map<String,?Object>的轉(zhuǎn)換方法

    平時(shí)對(duì)接口時(shí),經(jīng)常遇到j(luò)son字符串和map對(duì)象之間的交互,這篇文章主要給大家介紹了關(guān)于Java中JSONObject和Map<String,?Object>的轉(zhuǎn)換方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • 一文看懂springboot實(shí)現(xiàn)短信服務(wù)功能

    一文看懂springboot實(shí)現(xiàn)短信服務(wù)功能

    項(xiàng)目中的短信服務(wù)基本上上都會(huì)用到,簡單的注冊驗(yàn)證碼,消息通知等等都會(huì)用到。這篇文章主要介紹了springboot 實(shí)現(xiàn)短信服務(wù)功能,需要的朋友可以參考下
    2019-10-10
  • java代碼塊之簡易qq登錄界面及按鈕顏色設(shè)置代碼

    java代碼塊之簡易qq登錄界面及按鈕顏色設(shè)置代碼

    這篇文章主要介紹了java代碼塊之簡易qq登錄界面及按鈕顏色設(shè)置代碼,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • 解決java項(xiàng)目jar打包后讀取文件失敗的問題

    解決java項(xiàng)目jar打包后讀取文件失敗的問題

    這篇文章主要介紹了解決java項(xiàng)目jar打包后讀取文件失敗的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 創(chuàng)建java多線程程序

    創(chuàng)建java多線程程序

    Java 給多線程編程提供了內(nèi)置的支持。一條線程指的是進(jìn)程中一個(gè)單一順序的控制流,一個(gè)進(jìn)程中可以并發(fā)多個(gè)線程,每條線程并行執(zhí)行不同的任務(wù)。希望本篇文章能夠給你帶來幫助
    2021-06-06

最新評(píng)論