一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring中@Async注解執(zhí)行異步任務的方法

Spring中@Async注解執(zhí)行異步任務的方法

2021-05-07 13:14liaosilzu2007 Java教程

在業(yè)務處理中,有些業(yè)務使用異步的方式更為合理,這篇文章主要介紹了Spring中@Async注解執(zhí)行異步任務的方法,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

引言

在業(yè)務處理中,有些業(yè)務使用異步的方式更為合理。比如在某個業(yè)務邏輯中,把一些數據存入到redis緩存中,緩存只是一個輔助的功能,成功或者失敗對主業(yè)務并不會產生根本影響,這個過程可以通過異步的方法去進行。

Spring中通過在方法上設置@Async注解,可使得方法被異步調用。也就是說該方法會在調用時立即返回,而這個方法的實際執(zhí)行交給Spring的TaskExecutor去完成。

代碼示例

項目是一個普通的Spring的項目,Spring的配置文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:task="http://www.springframework.org/schema/task"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context.xsd
  http://www.springframework.org/schema/task
  http://www.springframework.org/schema/task/spring-task.xsd">
 
 <!-- 包掃描 -->
 <context:component-scan base-package="com.lzumetal.ssm"/>
 
 <!-- 執(zhí)行異步任務的線程池TaskExecutor -->
 <task:executor id="myexecutor" pool-size="5" />
 <task:annotation-driven executor="myexecutor"/>
 
</beans>

兩個Service類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.lzumetal.ssm.anotation.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
 
/**
 * 業(yè)務Service
 */
@Service
public class BusinessService {
 
 private static final Logger log = LoggerFactory.getLogger(BusinessService.class);
 
 @Autowired
 private CacheService cacheService;
 
 
 public void doBusiness() {
  log.error("start to deal with our business");
  cacheService.cacheData();
  log.error("comlete service operation");
 }
 
 /**
  * 獲取異步方法執(zhí)行的返回值
  */
 public void doBusinessWithAsyncReturn() throws ExecutionException, InterruptedException {
  log.error("start to deal with our business");
  Future<String> future = cacheService.cacheDataWithReturn();
  log.error(future.get()); //future.get()方法是會阻塞的
  log.error("comlete service operation");
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.lzumetal.ssm.anotation.service;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
 
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
 
/**
 * 緩存服務
 */
@Service
public class CacheService {
 
 private static final Logger log = LoggerFactory.getLogger(CacheService.class);
 
 
 @Async(value = "myexecutor") //指定執(zhí)行任務的TaskExecutor
 public void cacheData() {
  try {
   TimeUnit.SECONDS.sleep(3L);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  log.error("success store the result to cache");
 }
 
 
 @Async
 public Future<String> cacheDataWithReturn() {
  try {
   TimeUnit.SECONDS.sleep(3L);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  log.error("success store the result to cache");
  //返回的結果需要通過AsyncResult這個類包裝
  return new AsyncResult<>("Async operation success");
 }
}

測試類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.lzumetal.ssm.anotation.test;
 
import com.lzumetal.ssm.anotation.service.BusinessService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import java.util.concurrent.TimeUnit;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-context.xml"})
public class MainTest {
 
 
 @Autowired
 private BusinessService businessService;
 
 
 @Test
 public void test() throws InterruptedException {
  businessService.doBusiness();
  //不讓主線程過早結束,否則控制臺看不到異步方法中的輸出內容
  TimeUnit.SECONDS.sleep(5L); 
 }
 
 @Test
 public void testAsyncReturn() throws Exception {
  businessService.doBusinessWithAsyncReturn();
  TimeUnit.SECONDS.sleep(5L);
 }
 
}

執(zhí)行test()方法的結果:

22:20:33,207  INFO main support.DefaultTestContextBootstrapper:260 - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
22:20:33,226  INFO main support.DefaultTestContextBootstrapper:209 - Could not instantiate TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [javax/servlet/ServletContext]
22:20:33,227  INFO main support.DefaultTestContextBootstrapper:187 - Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@100fc185, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@643b1d11, org.springframework.test.context.support.DirtiesContextTestExecutionListener@2ef5e5e3, org.springframework.test.context.transaction.TransactionalTestExecutionListener@36d4b5c, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@6d00a15d]22:20:33,324  INFO main xml.XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [spring-context.xml]
22:20:33,585  INFO main support.GenericApplicationContext:583 - Refreshing org.springframework.context.support.GenericApplicationContext@4f7d0008: startup date [Wed May 30 22:20:33 CST 2018]; root of context hierarchy
22:20:33,763  INFO main concurrent.ThreadPoolTaskExecutor:165 - Initializing ExecutorService
22:20:33,766  INFO main support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [org.springframework.scheduling.config.TaskExecutorFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
22:20:33,767  INFO main support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
22:20:34,107 ERROR main service.BusinessService:24 - start to deal with our business
22:20:34,113 ERROR main service.BusinessService:26 - comlete service operation
22:20:37,166 ERROR myexecutor-1 service.CacheService:28 - success store the result to cache
22:20:39,117  INFO Thread-0 support.GenericApplicationContext:984 - Closing org.springframework.context.support.GenericApplicationContext@4f7d0008: startup date [Wed May 30 22:20:33 CST 2018]; root of context hierarchy
22:20:39,118  INFO Thread-0 concurrent.ThreadPoolTaskExecutor:203 - Shutting down ExecutorService

執(zhí)行testAsyncReturn()方法的結果:

21:38:16,908  INFO main support.DefaultTestContextBootstrapper:260 - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
21:38:16,926  INFO main support.DefaultTestContextBootstrapper:209 - Could not instantiate TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [javax/servlet/ServletContext]
21:38:16,927  INFO main support.DefaultTestContextBootstrapper:187 - Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@100fc185, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@643b1d11, org.springframework.test.context.support.DirtiesContextTestExecutionListener@2ef5e5e3, org.springframework.test.context.transaction.TransactionalTestExecutionListener@36d4b5c, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@6d00a15d]21:38:17,025  INFO main xml.XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [spring-context.xml]
21:38:17,263  INFO main support.GenericApplicationContext:583 - Refreshing org.springframework.context.support.GenericApplicationContext@4f7d0008: startup date [Wed May 30 21:38:17 CST 2018]; root of context hierarchy
21:38:17,405  INFO main concurrent.ThreadPoolTaskExecutor:165 - Initializing ExecutorService
21:38:17,407  INFO main support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [org.springframework.scheduling.config.TaskExecutorFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
21:38:17,407  INFO main support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
21:38:17,692 ERROR main service.BusinessService:35 - start to deal with our business
21:38:20,833 ERROR myexecutor-1 service.CacheService:39 - success store the result to cache
21:38:20,834 ERROR main service.BusinessService:37 - Async operation success
21:38:20,835 ERROR main service.BusinessService:38 - comlete service operation
21:38:25,838  INFO Thread-0 support.GenericApplicationContext:984 - Closing org.springframework.context.support.GenericApplicationContext@4f7d0008: startup date [Wed May 30 21:38:17 CST 2018]; root of context hierarchy
21:38:25,839  INFO Thread-0 concurrent.ThreadPoolTaskExecutor:203 - Shutting down ExecutorService

@Async的使用注意點

  1. 返回值:不要返回值直接void;需要返回值用AsyncResult或者CompletableFuture
  2. 可自定義執(zhí)行器并指定例如:@Async("otherExecutor")
  3. @Async必須不同類間調用: A類—>B類.C方法()(@Async注釋在B類/方法中),如果在同一個類中調用,會變同步執(zhí)行,例如:A類.B()—>A類.@Async C()。
  4. @Async也可以加到類,表示這個類的所有方法都是異步執(zhí)行,并且方法上的注解會覆蓋類上的注解。但一般不這么用!

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://segmentfault.com/a/1190000015190901

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 激情婷婷成人亚洲综合 | 午夜办公室 | 特级淫片欧美高清视频蜜桃 | xxx久久| 亚洲国产精品一在线观看 | 大好硬好深好爽想要视频 | 特黄a大片免费视频 | 蜜桃传媒在线 | 日本色播 | 亚洲波霸 | 12一14性xxxxx国外 | 欧美va在线 | 脱jk裙的美女露小内内无遮挡 | 5g影院天天5g天天爽大陆 | 国产一区私人高清影院 | 女海盗斯蒂内塔的复仇2免费观看 | 性xxxxxxx18老师| 午夜国产福利视频一区 | 青柠影院在线观看免费完整版1 | 亚洲欧美日韩国产一区图片 | 国产一线天 | 成人福利视频网址 | 91精品综合久久久久m3u8 | 国产一区二区不卡 | 国产亚洲玖玖玖在线观看 | 国产亚洲欧美日韩俺去了 | 草莓秋葵菠萝蜜绿巨人污 | 亚洲午夜精品久久久久久成年 | 91免费播放人人爽人人快乐 | 婷婷色在线 | 日本高清视频在线的 | 波多野 在线 | 无码国产成人777爽死在线观看 | 小舞同人18av黄漫网站 | 亚洲国产欧美在线人网站 | 456在线观看 | 国产1广场舞丰满老女偷 | 91噜噜噜在线观看 | 国产精亚洲视频 | 欧美区日韩区 | 免费观看一级一片 |