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

淺談Spring @Async異步線(xiàn)程池用法總結(jié)

 更新時(shí)間:2017年07月25日 15:10:09   作者:hry2015  
本篇文章主要介紹了淺談Spring @Async異步線(xiàn)程池用法總結(jié),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文介紹了Spring @Async異步線(xiàn)程池用法總結(jié),分享給大家,希望對(duì)大家有幫助

1. TaskExecutor

spring異步線(xiàn)程池的接口類(lèi),其實(shí)質(zhì)是Java.util.concurrent.Executor

Spring 已經(jīng)實(shí)現(xiàn)的異常線(xiàn)程池:

1. SimpleAsyncTaskExecutor:不是真的線(xiàn)程池,這個(gè)類(lèi)不重用線(xiàn)程,每次調(diào)用都會(huì)創(chuàng)建一個(gè)新的線(xiàn)程。
2. SyncTaskExecutor:這個(gè)類(lèi)沒(méi)有實(shí)現(xiàn)異步調(diào)用,只是一個(gè)同步操作。只適用于不需要多線(xiàn)程的地方
3. ConcurrentTaskExecutor:Executor的適配類(lèi),不推薦使用。如果ThreadPoolTaskExecutor不滿(mǎn)足要求時(shí),才用考慮使用這個(gè)類(lèi)
4. SimpleThreadPoolTaskExecutor:是Quartz的SimpleThreadPool的類(lèi)。線(xiàn)程池同時(shí)被quartz和非quartz使用,才需要使用此類(lèi)
5. ThreadPoolTaskExecutor :最常使用,推薦。 其實(shí)質(zhì)是對(duì)java.util.concurrent.ThreadPoolExecutor的包裝

2. @Async

spring對(duì)過(guò)@Async定義異步任務(wù)

異步的方法有3種

1. 最簡(jiǎn)單的異步調(diào)用,返回值為void
2. 帶參數(shù)的異步調(diào)用 異步方法可以傳入?yún)?shù)
3. 異常調(diào)用返回Future

詳細(xì)見(jiàn)代碼:

@Component
public class AsyncDemo {
  private static final Logger log = LoggerFactory.getLogger(AsyncDemo.class);

  /**
   * 最簡(jiǎn)單的異步調(diào)用,返回值為void
   */
  @Async
  public void asyncInvokeSimplest() {
    log.info("asyncSimplest");
  }

  /**
   * 帶參數(shù)的異步調(diào)用 異步方法可以傳入?yún)?shù)
   * 
   * @param s
   */
  @Async
  public void asyncInvokeWithParameter(String s) {
    log.info("asyncInvokeWithParameter, parementer={}", s);
  }

  /**
   * 異常調(diào)用返回Future
   * 
   * @param i
   * @return
   */
  @Async
  public Future<String> asyncInvokeReturnFuture(int i) {
    log.info("asyncInvokeReturnFuture, parementer={}", i);
    Future<String> future;
    try {
      Thread.sleep(1000 * 1);
      future = new AsyncResult<String>("success:" + i);
    } catch (InterruptedException e) {
      future = new AsyncResult<String>("error");
    }
    return future;
  }

}

以上的異步方法和普通的方法調(diào)用相同

asyncDemo.asyncInvokeSimplest();
asyncDemo.asyncInvokeWithException("test");
Future<String> future = asyncDemo.asyncInvokeReturnFuture(100);
System.out.println(future.get());

3. Spring 開(kāi)啟異步配置

Spring有兩種方法啟動(dòng)配置

1. 注解
2. XML

3.1 通過(guò)注解實(shí)現(xiàn)

要啟動(dòng)異常方法還需要以下配置

1. @EnableAsync 此注解開(kāi)戶(hù)異步調(diào)用功能

2. public AsyncTaskExecutor taskExecutor() 方法自定義自己的線(xiàn)程池,線(xiàn)程池前綴”Anno-Executor”。如果不定義,則使用系統(tǒng)默認(rèn)的線(xiàn)程池。

@SpringBootApplication
@EnableAsync // 啟動(dòng)異步調(diào)用
public class AsyncApplicationWithAnnotation {
  private static final Logger log = LoggerFactory.getLogger(AsyncApplicationWithAnnotation.class);

  /**
   * 自定義異步線(xiàn)程池
   * @return
   */
  @Bean
  public AsyncTaskExecutor taskExecutor() { 
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
    executor.setThreadNamePrefix("Anno-Executor");
    executor.setMaxPoolSize(10); 

    // 設(shè)置拒絕策略
    executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
      @Override
      public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // .....
      }
    });
    // 使用預(yù)定義的異常處理類(lèi)
    // executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

    return executor; 
  } 

  public static void main(String[] args) {
    log.info("Start AsyncApplication.. ");
    SpringApplication.run(AsyncApplicationWithAnnotation.class, args);
  }
}

以上的異常方法和普通的方法調(diào)用相同

@RunWith(SpringRunner.class)
@SpringBootTest(classes=AsyncApplicationWithAnnotation.class)
public class AsyncApplicationWithAnnotationTests {
  @Autowired
  private AsyncDemo asyncDemo;

  @Test
  public void contextLoads() throws InterruptedException, ExecutionException {
    asyncDemo.asyncInvokeSimplest();
    asyncDemo.asyncInvokeWithParameter("test");
    Future<String> future = asyncDemo.asyncInvokeReturnFuture(100);
    System.out.println(future.get());
  }
}

執(zhí)行測(cè)試用例,輸出內(nèi)容如下:

可以看出主線(xiàn)程的名稱(chēng)為main; 異步方法則使用 Anno-Executor1,可見(jiàn)異常線(xiàn)程池起作用了

2017-03-28 20:00:07.731 INFO 5144 --- [ Anno-Executor1] c.hry.spring.async.annotation.AsyncDemo : asyncSimplest
2017-03-28 20:00:07.732 INFO 5144 --- [ Anno-Executor1] c.hry.spring.async.annotation.AsyncDemo : asyncInvokeWithParameter, parementer=test
2017-03-28 20:00:07.751 INFO 5144 --- [ Anno-Executor1] c.hry.spring.async.annotation.AsyncDemo : asyncInvokeReturnFuture, parementer=100
success:100
2017-03-28 20:00:08.757 INFO 5144 --- [    Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@47af7f3d: startup date [Tue Mar 28 20:00:06 CST 2017]; root of context hierarchy

3.2 通過(guò)XML實(shí)現(xiàn)

Bean文件配置: spring_async.xml

1. 線(xiàn)程的前綴為xmlExecutor
2. 啟動(dòng)異步線(xiàn)程池配置

  <!-- 等價(jià)于 @EnableAsync, executor指定線(xiàn)程池 -->
  <task:annotation-driven executor="xmlExecutor"/>
  <!-- id指定線(xiàn)程池產(chǎn)生線(xiàn)程名稱(chēng)的前綴 -->
  <task:executor
    id="xmlExecutor"
    pool-size="5-25"
    queue-capacity="100"
    keep-alive="120"
    rejection-policy="CALLER_RUNS"/>

線(xiàn)程池參數(shù)說(shuō)明

1. ‘id' : 線(xiàn)程的名稱(chēng)的前綴

2. ‘pool-size':線(xiàn)程池的大小。支持范圍”min-max”和固定值(此時(shí)線(xiàn)程池core和max sizes相同)

3. ‘queue-capacity' :排隊(duì)隊(duì)列長(zhǎng)度

○ The main idea is that when a task is submitted, the executor will first try to use a free thread if the number of active threads is currently less than the core size.
○ If the core size has been reached, then the task will be added to the queue as long as its capacity has not yet been reached.
○ Only then, if the queue's capacity has been reached, will the executor create a new thread beyond the core size.
○ If the max size has also been reached, then the executor will reject the task.
○ By default, the queue is unbounded, but this is rarely the desired configuration because it can lead to OutOfMemoryErrors if enough tasks are added to that queue while all pool threads are busy.

4. ‘rejection-policy': 對(duì)拒絕的任務(wù)處理策略

○ In the default ThreadPoolExecutor.AbortPolicy, the handler throws a runtime RejectedExecutionException upon rejection.
○ In ThreadPoolExecutor.CallerRunsPolicy, the thread that invokes execute itself runs the task. This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted.
○ In ThreadPoolExecutor.DiscardPolicy, a task that cannot be executed is simply dropped.
○ In ThreadPoolExecutor.DiscardOldestPolicy, if the executor is not shut down, the task at the head of the work queue is dropped, and then execution is retried (which can fail again, causing this to be repeated.)

5. ‘keep-alive' : 線(xiàn)程保活時(shí)間(單位秒)

setting determines the time limit (in seconds) for which threads may remain idle before being terminated. If there are more than the core number of threads currently in the pool, after waiting this amount of time without processing a task, excess threads will get terminated. A time value of zero will cause excess threads to terminate immediately after executing a task without remaining follow-up work in the task queue()

異步線(xiàn)程池

@SpringBootApplication
@ImportResource("classpath:/async/spring_async.xml")
public class AsyncApplicationWithXML {
  private static final Logger log = LoggerFactory.getLogger(AsyncApplicationWithXML.class);

  public static void main(String[] args) {
    log.info("Start AsyncApplication.. ");
    SpringApplication.run(AsyncApplicationWithXML.class, args);
  }
}

測(cè)試用例

@RunWith(SpringRunner.class)
@SpringBootTest(classes=AsyncApplicationWithXML.class)
public class AsyncApplicationWithXMLTest {
  @Autowired
  private AsyncDemo asyncDemo;

  @Test
  public void contextLoads() throws InterruptedException, ExecutionException {
    asyncDemo.asyncInvokeSimplest();
    asyncDemo.asyncInvokeWithParameter("test");
    Future<String> future = asyncDemo.asyncInvokeReturnFuture(100);
    System.out.println(future.get());
  }
}

運(yùn)行測(cè)試用例,輸出內(nèi)容如下:

可以看出主線(xiàn)程的名稱(chēng)為main; 異步方法則使用 xmlExecutor-x,可見(jiàn)異常線(xiàn)程池起作用了

2017-03-28 20:12:10.540 INFO 12948 --- [      main] c.h.s.a.xml.AsyncApplicationWithXMLTest : Started AsyncApplicationWithXMLTest in 1.441 seconds (JVM running for 2.201)
2017-03-28 20:12:10.718 INFO 12948 --- [ xmlExecutor-2] com.hry.spring.async.xml.AsyncDemo    : asyncInvokeWithParameter, parementer=test
2017-03-28 20:12:10.721 INFO 12948 --- [ xmlExecutor-1] com.hry.spring.async.xml.AsyncDemo    : asyncSimplest
2017-03-28 20:12:10.722 INFO 12948 --- [ xmlExecutor-3] com.hry.spring.async.xml.AsyncDemo    : asyncInvokeReturnFuture, parementer=100
success:100
2017-03-28 20:12:11.729 INFO 12948 --- [    Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@71809907: startup date [Tue Mar 28 20:12:09 CST 2017]; root of context hierarchy

4. 對(duì)異步方法的異常處理

在調(diào)用方法時(shí),可能出現(xiàn)方法中拋出異常的情況。在異步中主要有有兩種異常處理方法:

1. 對(duì)于方法返回值是Futrue的異步方法: a) 一種是在調(diào)用future的get時(shí)捕獲異常; b) 在異常方法中直接捕獲異常

2. 對(duì)于返回值是void的異步方法:通過(guò)AsyncUncaughtExceptionHandler處理異常

AsyncExceptionDemo:

@Component
public class AsyncExceptionDemo {
  private static final Logger log = LoggerFactory.getLogger(AsyncExceptionDemo.class);

  /**
   * 最簡(jiǎn)單的異步調(diào)用,返回值為void
   */
  @Async
  public void asyncInvokeSimplest() {
    log.info("asyncSimplest");
  }

  /**
   * 帶參數(shù)的異步調(diào)用 異步方法可以傳入?yún)?shù)
   * 對(duì)于返回值是void,異常會(huì)被AsyncUncaughtExceptionHandler處理掉
   * @param s
   */
  @Async
  public void asyncInvokeWithException(String s) {
    log.info("asyncInvokeWithParameter, parementer={}", s);
    throw new IllegalArgumentException(s);
  }

  /**
   * 異常調(diào)用返回Future
   * 對(duì)于返回值是Future,不會(huì)被AsyncUncaughtExceptionHandler處理,需要我們?cè)诜椒ㄖ胁东@異常并處理
   * 或者在調(diào)用方在調(diào)用Futrue.get時(shí)捕獲異常進(jìn)行處理
   * 
   * @param i
   * @return
   */
  @Async
  public Future<String> asyncInvokeReturnFuture(int i) {
    log.info("asyncInvokeReturnFuture, parementer={}", i);
    Future<String> future;
    try {
      Thread.sleep(1000 * 1);
      future = new AsyncResult<String>("success:" + i);
      throw new IllegalArgumentException("a");
    } catch (InterruptedException e) {
      future = new AsyncResult<String>("error");
    } catch(IllegalArgumentException e){
      future = new AsyncResult<String>("error-IllegalArgumentException");
    }
    return future;
  }

}

實(shí)現(xiàn)AsyncConfigurer接口對(duì)異常線(xiàn)程池更加細(xì)粒度的控制

a) 創(chuàng)建線(xiàn)程自己的線(xiàn)程池

b) 對(duì)void方法拋出的異常處理的類(lèi)AsyncUncaughtExceptionHandler

/**
 * 通過(guò)實(shí)現(xiàn)AsyncConfigurer自定義異常線(xiàn)程池,包含異常處理
 * 
 * @author hry
 *
 */
@Service
public class MyAsyncConfigurer implements AsyncConfigurer{
  private static final Logger log = LoggerFactory.getLogger(MyAsyncConfigurer.class);

  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); 
    threadPool.setCorePoolSize(1); 
    threadPool.setMaxPoolSize(1); 
    threadPool.setWaitForTasksToCompleteOnShutdown(true); 
    threadPool.setAwaitTerminationSeconds(60 * 15); 
    threadPool.setThreadNamePrefix("MyAsync-");
    threadPool.initialize();
    return threadPool; 
  }

  @Override
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
     return new MyAsyncExceptionHandler(); 
  }

  /**
   * 自定義異常處理類(lèi)
   * @author hry
   *
   */
  class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler { 

    @Override 
    public void handleUncaughtException(Throwable throwable, Method method, Object... obj) { 
      log.info("Exception message - " + throwable.getMessage()); 
      log.info("Method name - " + method.getName()); 
      for (Object param : obj) { 
        log.info("Parameter value - " + param); 
      } 
    } 

  } 

}

@SpringBootApplication
@EnableAsync // 啟動(dòng)異步調(diào)用
public class AsyncApplicationWithAsyncConfigurer {
  private static final Logger log = LoggerFactory.getLogger(AsyncApplicationWithAsyncConfigurer.class);

  public static void main(String[] args) {
    log.info("Start AsyncApplication.. ");
    SpringApplication.run(AsyncApplicationWithAsyncConfigurer.class, args);
  }


}

測(cè)試代碼

@RunWith(SpringRunner.class)
@SpringBootTest(classes=AsyncApplicationWithAsyncConfigurer.class)
public class AsyncApplicationWithAsyncConfigurerTests {
  @Autowired
  private AsyncExceptionDemo asyncDemo;

  @Test
  public void contextLoads() throws InterruptedException, ExecutionException {
    asyncDemo.asyncInvokeSimplest();
    asyncDemo.asyncInvokeWithException("test");
    Future<String> future = asyncDemo.asyncInvokeReturnFuture(100);
    System.out.println(future.get());
  }
}

運(yùn)行測(cè)試用例

MyAsyncConfigurer 捕獲AsyncExceptionDemo 對(duì)象在調(diào)用asyncInvokeWithException的異常

2017-04-02 16:01:45.591 INFO 11152 --- [   MyAsync-1] c.h.s.a.exception.AsyncExceptionDemo   : asyncSimplest
2017-04-02 16:01:45.605 INFO 11152 --- [   MyAsync-1] c.h.s.a.exception.AsyncExceptionDemo   : asyncInvokeWithParameter, parementer=test
2017-04-02 16:01:45.608 INFO 11152 --- [   MyAsync-1] c.h.s.async.exception.MyAsyncConfigurer : Exception message - test
2017-04-02 16:01:45.608 INFO 11152 --- [   MyAsync-1] c.h.s.async.exception.MyAsyncConfigurer : Method name - asyncInvokeWithException
2017-04-02 16:01:45.608 INFO 11152 --- [   MyAsync-1] c.h.s.async.exception.MyAsyncConfigurer : Parameter value - test
2017-04-02 16:01:45.608 INFO 11152 --- [   MyAsync-1] c.h.s.a.exception.AsyncExceptionDemo   : asyncInvokeReturnFuture, parementer=100
error-IllegalArgumentException
2017-04-02 16:01:46.656 INFO 11152 --- [    Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@47af7f3d: startup date [Sun Apr 02 16:01:44 CST 2017]; root of context hierarchy

5. 源碼地址

代碼的GITHUB地址

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

相關(guān)文章

  • mybatis-plus配置日志兩種實(shí)現(xiàn)方式

    mybatis-plus配置日志兩種實(shí)現(xiàn)方式

    這篇文章主要給大家介紹了關(guān)于mybatis-plus配置日志兩種實(shí)現(xiàn)方式的相關(guān)資料,Mybatis-plus集成了日志框架,可以將程序運(yùn)行時(shí)產(chǎn)生的日志進(jìn)行記錄,方便開(kāi)發(fā)人員進(jìn)行問(wèn)題排查,需要的朋友可以參考下
    2023-09-09
  • 如何把第三方服務(wù)注冊(cè)到spring項(xiàng)目容器中

    如何把第三方服務(wù)注冊(cè)到spring項(xiàng)目容器中

    這篇文章主要為大家介紹了如何把第三方服務(wù)注冊(cè)到spring項(xiàng)目容器中,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • springboot整合mybatis plus與druid詳情

    springboot整合mybatis plus與druid詳情

    這篇文章主要介紹了springboot整合mybatis plus與druid詳情,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的下伙伴可以參考一下
    2022-09-09
  • SpringBoot使用Thymeleaf自定義標(biāo)簽的實(shí)例代碼

    SpringBoot使用Thymeleaf自定義標(biāo)簽的實(shí)例代碼

    這篇文章主要介紹了SpringBoot使用Thymeleaf自定義標(biāo)簽的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Spring中的事件監(jiān)聽(tīng)器使用學(xué)習(xí)記錄

    Spring中的事件監(jiān)聽(tīng)器使用學(xué)習(xí)記錄

    Spring框架中的事件監(jiān)聽(tīng)機(jī)制是一種設(shè)計(jì)模式,它允許你定義和觸發(fā)事件,同時(shí)允許其他組件監(jiān)聽(tīng)這些事件并在事件發(fā)生時(shí)作出響應(yīng),這篇文章主要介紹了Spring中的事件監(jiān)聽(tīng)器使用學(xué)習(xí),需要的朋友可以參考下
    2024-07-07
  • java匿名內(nèi)部類(lèi)實(shí)例代碼詳解

    java匿名內(nèi)部類(lèi)實(shí)例代碼詳解

    這篇文章主要介紹了java匿名內(nèi)部類(lèi)實(shí)例代碼詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • java9在interface中定義私有方法詳解

    java9在interface中定義私有方法詳解

    在本篇內(nèi)容里小編給大家整理的是一篇關(guān)于java9在interface中定義私有方法,有興趣的朋友們可以學(xué)習(xí)下。
    2020-10-10
  • Java實(shí)現(xiàn)冒泡排序算法

    Java實(shí)現(xiàn)冒泡排序算法

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)冒泡排序算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 關(guān)于maven配置項(xiàng)目一直提示程序包不存在以及scope的坑

    關(guān)于maven配置項(xiàng)目一直提示程序包不存在以及scope的坑

    這篇文章主要介紹了關(guān)于maven配置項(xiàng)目一直提示程序包不存在以及scope的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • java教程之二個(gè)arraylist排序的示例分享

    java教程之二個(gè)arraylist排序的示例分享

    常常遇到數(shù)組排序的問(wèn)題,下面提供二個(gè)java的arraylist排序示例,需要的朋友可以參考下
    2014-03-03

最新評(píng)論