亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring Boot Async異步執行任務的操作方法

發布時間:2020-08-14 14:00:27 來源:億速云 閱讀:169 作者:小新 欄目:開發技術

小編給大家分享一下Spring Boot Async異步執行任務的操作方法,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

異步調用就是不用等待結果的返回就執行后面的邏輯,同步調用則需要等帶結果再執行后面的邏輯。

通常我們使用異步操作都會去創建一個線程執行一段邏輯,然后把這個線程丟到線程池中去執行,代碼如下:

ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(() -> {
  try {
    // 業務邏輯
  } catch (Exception e) {
    e.printStackTrace();
  } finally {
  }
 });

這樣的方式看起來沒那么優雅,盡管用了java的lambda。在Spring Boot中有一種更簡單的方式來執行異步操作,只需要一個@Async注解即可。

@Async
public void saveLog() {
  System.err.println(Thread.currentThread().getName());
}

我們可以直接在Controller中調用這個業務方法,它就是異步執行的,會在默認的線程池中去執行。需要注意的是一定要在外部的類中去調用這個方法,如果在本類調用是不起作用的,比如this.saveLog()。 最后在啟動類上開啟異步任務的執行,添加@EnableAsync即可。

另外關于執行異步任務的線程池我們也可以自定義,首先我們定義一個線程池的配置類,用來配置一些參數,具體代碼如下:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; 
/**
 * 異步任務線程池配置
 * 
 * @author yinjihuan
 */
@Configuration
@ConfigurationProperties(prefix = "spring.task.pool")
public class TaskThreadPoolConfig { 
  //核心線程數
  private int corePoolSize = 5; 
  //最大線程數
  private int maxPoolSize = 50; 
  //線程池維護線程所允許的空閑時間
  private int keepAliveSeconds = 60; 
  //隊列長度
  private int queueCapacity = 10000;
  //線程名稱前綴
  private String threadNamePrefix = "FSH-AsyncTask-";
  public String getThreadNamePrefix() {
    return threadNamePrefix;
  }
  public void setThreadNamePrefix(String threadNamePrefix) {
    this.threadNamePrefix = threadNamePrefix;
  }
  public int getCorePoolSize() {
    return corePoolSize;
  }
  public void setCorePoolSize(int corePoolSize) {
    this.corePoolSize = corePoolSize;
  }
  public int getMaxPoolSize() {
    return maxPoolSize;
  }
  public void setMaxPoolSize(int maxPoolSize) {
    this.maxPoolSize = maxPoolSize;
  }
  public int getKeepAliveSeconds() {
    return keepAliveSeconds;
  }
  public void setKeepAliveSeconds(int keepAliveSeconds) {
    this.keepAliveSeconds = keepAliveSeconds;
  }
  public int getQueueCapacity() {
    return queueCapacity;
  }
  public void setQueueCapacity(int queueCapacity) {
    this.queueCapacity = queueCapacity;
  }
} 

然后我們重新定義線程池的配置:

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration 
public class AsyncTaskExecutePool implements AsyncConfigurer {  
  private Logger logger = LoggerFactory.getLogger(AsyncTaskExecutePool.class);

  @Autowired  
  private TaskThreadPoolConfig config;

  @Override 
  public Executor getAsyncExecutor() { 
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
    executor.setCorePoolSize(config.getCorePoolSize());  
    executor.setMaxPoolSize(config.getMaxPoolSize());  
    executor.setQueueCapacity(config.getQueueCapacity());  
    executor.setKeepAliveSeconds(config.getKeepAliveSeconds());  
    executor.setThreadNamePrefix(config.getThreadNamePrefix());
    //線程池對拒絕任務(無線程可用)的處理策略,目前只支持AbortPolicy、CallerRunsPolicy
    //AbortPolicy:直接拋出java.util.concurrent.RejectedExecutionException異常 -->
    //CallerRunsPolicy:主線程直接執行該任務,執行完之后嘗試添加下一個任務到線程池中,可以有效降低向線程池內添加任務的速度 -->
    //DiscardOldestPolicy:拋棄舊的任務、暫不支持;會導致被丟棄的任務無法再次被執行 -->
    //DiscardPolicy:拋棄當前任務、暫不支持;會導致被丟棄的任務無法再次被執行 -->
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 
    executor.initialize();  
    return executor;  
  } 
  @Override 
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {// 異步任務中異常處理 
    return new AsyncUncaughtExceptionHandler() { 
      @Override 
      public void handleUncaughtException(Throwable arg0, Method arg1, Object... arg2) { 
        logger.error("=========================="+arg0.getMessage()+"=======================", arg0); 
        logger.error("exception method:" + arg1.getName()); 
      } 
    }; 
  }  
} 

配置完之后我們的異步任務執行的線程池就是我們自定義的了,我們可以通過在屬性文件里面配置線程池的大小等等信息,也可以使用默認的配置:

spring.task.pool.maxPoolSize=100

最后講下線程池配置的拒絕策略,當我們的線程數量高于線程池的處理速度時,任務會被緩存到本地的隊列中,隊列也是有大小的,如果超過了這個大小,我們需要有拒絕的策略,不然就會內存溢出了,目前支持2種拒絕策略:

  • AbortPolicy: 直接拋出java.util.concurrent.RejectedExecutionException異常
  • CallerRunsPolicy: 主線程直接執行該任務,執行完之后嘗試添加下一個任務到線程池中,可以有效降低向線程池內添加任務的速度
  • 建議大家用CallerRunsPolicy策略,因為當隊列中的任務滿了之后,如果直接拋異常,那么這個任務就會被丟棄,如果是CallerRunsPolicy策略會用主線程去執行,就是同步執行,最起碼這樣任務不會丟棄。

以上是Spring Boot Async異步執行任務的操作方法的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

远安县| 江门市| 精河县| 关岭| 南岸区| 社旗县| 图木舒克市| 江永县| 景宁| 德安县| 富顺县| 台北县| 万安县| 冷水江市| 洛南县| 昌平区| 山阴县| 龙南县| 宁海县| 宁都县| 通道| 江门市| 万载县| 广灵县| 巍山| 深圳市| 虹口区| 尚义县| 马龙县| 文登市| 新竹县| 胶州市| 同心县| 大悟县| 育儿| 郑州市| 安西县| 嵊州市| 渝中区| 武汉市| 长宁县|