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

Spring Boot Async異步執(zhí)行任務(wù)過程詳解

 更新時(shí)間:2020年08月13日 10:17:45   作者:猿天地  
這篇文章主要介紹了Spring Boot Async異步執(zhí)行任務(wù)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

異步調(diào)用就是不用等待結(jié)果的返回就執(zhí)行后面的邏輯,同步調(diào)用則需要等帶結(jié)果再執(zhí)行后面的邏輯。

通常我們使用異步操作都會(huì)去創(chuàng)建一個(gè)線程執(zhí)行一段邏輯,然后把這個(gè)線程丟到線程池中去執(zhí)行,代碼如下:

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

這樣的方式看起來沒那么優(yōu)雅,盡管用了java的lambda。在Spring Boot中有一種更簡(jiǎn)單的方式來執(zhí)行異步操作,只需要一個(gè)@Async注解即可。

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

我們可以直接在Controller中調(diào)用這個(gè)業(yè)務(wù)方法,它就是異步執(zhí)行的,會(huì)在默認(rèn)的線程池中去執(zhí)行。需要注意的是一定要在外部的類中去調(diào)用這個(gè)方法,如果在本類調(diào)用是不起作用的,比如this.saveLog()。 最后在啟動(dòng)類上開啟異步任務(wù)的執(zhí)行,添加@EnableAsync即可。

另外關(guān)于執(zhí)行異步任務(wù)的線程池我們也可以自定義,首先我們定義一個(gè)線程池的配置類,用來配置一些參數(shù),具體代碼如下:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; 
/**
 * 異步任務(wù)線程池配置
 * 
 * @author yinjihuan
 */
@Configuration
@ConfigurationProperties(prefix = "spring.task.pool")
public class TaskThreadPoolConfig { 
  //核心線程數(shù)
  private int corePoolSize = 5; 
  //最大線程數(shù)
  private int maxPoolSize = 50; 
  //線程池維護(hù)線程所允許的空閑時(shí)間
  private int keepAliveSeconds = 60; 
  //隊(duì)列長(zhǎng)度
  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());
    //線程池對(duì)拒絕任務(wù)(無線程可用)的處理策略,目前只支持AbortPolicy、CallerRunsPolicy
    //AbortPolicy:直接拋出java.util.concurrent.RejectedExecutionException異常 -->
    //CallerRunsPolicy:主線程直接執(zhí)行該任務(wù),執(zhí)行完之后嘗試添加下一個(gè)任務(wù)到線程池中,可以有效降低向線程池內(nèi)添加任務(wù)的速度 -->
    //DiscardOldestPolicy:拋棄舊的任務(wù)、暫不支持;會(huì)導(dǎo)致被丟棄的任務(wù)無法再次被執(zhí)行 -->
    //DiscardPolicy:拋棄當(dāng)前任務(wù)、暫不支持;會(huì)導(dǎo)致被丟棄的任務(wù)無法再次被執(zhí)行 -->
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 
    executor.initialize();  
    return executor;  
  } 
  @Override 
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {// 異步任務(wù)中異常處理 
    return new AsyncUncaughtExceptionHandler() { 
      @Override 
      public void handleUncaughtException(Throwable arg0, Method arg1, Object... arg2) { 
        logger.error("=========================="+arg0.getMessage()+"=======================", arg0); 
        logger.error("exception method:" + arg1.getName()); 
      } 
    }; 
  }  
} 

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

spring.task.pool.maxPoolSize=100

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

  • AbortPolicy: 直接拋出java.util.concurrent.RejectedExecutionException異常
  • CallerRunsPolicy: 主線程直接執(zhí)行該任務(wù),執(zhí)行完之后嘗試添加下一個(gè)任務(wù)到線程池中,可以有效降低向線程池內(nèi)添加任務(wù)的速度
  • 建議大家用CallerRunsPolicy策略,因?yàn)楫?dāng)隊(duì)列中的任務(wù)滿了之后,如果直接拋異常,那么這個(gè)任務(wù)就會(huì)被丟棄,如果是CallerRunsPolicy策略會(huì)用主線程去執(zhí)行,就是同步執(zhí)行,最起碼這樣任務(wù)不會(huì)丟棄。

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

相關(guān)文章

  • Java設(shè)計(jì)模式之建造者模式的示例詳解

    Java設(shè)計(jì)模式之建造者模式的示例詳解

    建造者模式,是一種對(duì)象構(gòu)建模式?它可以將復(fù)雜對(duì)象的建造過程抽象出來,使這個(gè)抽象過程的不同實(shí)現(xiàn)方法可以構(gòu)造出不同表現(xiàn)的對(duì)象。本文將通過示例講解建造者模式,需要的可以參考一下
    2022-10-10
  • SpringBoot攔截器使用精講

    SpringBoot攔截器使用精講

    攔截器可以根據(jù) URL 對(duì)請(qǐng)求進(jìn)行攔截,主要應(yīng)用于登陸校驗(yàn)、權(quán)限驗(yàn)證、亂碼解決、性能監(jiān)控和異常處理等功能上。SpringBoot同樣提供了攔截器功能。 本文將為大家詳細(xì)介紹一下
    2021-12-12
  • java 終止線程的4種方式小結(jié)

    java 終止線程的4種方式小結(jié)

    本文主要介紹了java終止線程的4種方式小結(jié),包含布爾標(biāo)志位,interrupt()方法,stop()方法和Thread.interrupt()方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • Java中解決跨域問題的方法匯總(建議收藏)

    Java中解決跨域問題的方法匯總(建議收藏)

    我們?cè)陂_發(fā)過程中經(jīng)常會(huì)遇到前后端分離而導(dǎo)致的跨域問題,導(dǎo)致無法獲取返回結(jié)果,下面給大家介紹Java中解決跨域問題的方法匯總,感興趣的朋友跟隨小編一起看看吧
    2024-04-04
  • Spring中@ExceptionHandler注解的使用方式

    Spring中@ExceptionHandler注解的使用方式

    這篇文章主要介紹了Spring中@ExceptionHandler注解的使用方式,@ExceptionHandler注解我們一般是用來自定義異常的,可以認(rèn)為它是一個(gè)異常攔截器(處理器),需要的朋友可以參考下
    2024-01-01
  • Java實(shí)現(xiàn)五子棋網(wǎng)絡(luò)版

    Java實(shí)現(xiàn)五子棋網(wǎng)絡(luò)版

    這篇文章主要為大家詳細(xì)介紹了基于Java編寫的網(wǎng)絡(luò)五子棋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • Springboot錯(cuò)誤頁面和錯(cuò)誤信息定制操作

    Springboot錯(cuò)誤頁面和錯(cuò)誤信息定制操作

    這篇文章主要介紹了Springboot錯(cuò)誤頁面和錯(cuò)誤信息定制操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • mybatis查詢語句揭秘之封裝數(shù)據(jù)

    mybatis查詢語句揭秘之封裝數(shù)據(jù)

    這篇文章主要給大家介紹了關(guān)于mybatis查詢語句揭秘之封裝數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用mybatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Spring?main方法中如何調(diào)用Dao層和Service層的方法

    Spring?main方法中如何調(diào)用Dao層和Service層的方法

    這篇文章主要介紹了Spring?main方法中調(diào)用Dao層和Service層的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Mybatis中注解@MapKey的使用詳解

    Mybatis中注解@MapKey的使用詳解

    mybatis的原身是ibatis,現(xiàn)在已經(jīng)脫離了apache基金會(huì)。這篇文章主要介紹了Mybatis中注解@MapKey的使用的相關(guān)資料,需要的朋友可以參考下
    2016-10-10

最新評(píng)論