好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用Spring开启@Async异步方式(javaconfig配置)

Spring开启@Async异步(javaconfig配置)

在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。

应用场景

某些耗时较长的而用户不需要等待该方法的处理结果 某些耗时较长的方法,后面的程序不需要用到这个方法的处理结果时

代码

创建AsyncTask

?

1

2

3

4

5

6

7

8

9

10

11

12

13

/**

  * 异步任务

  *

  * @author Peng

  */

public class AsyncTask {

     @Async

     public void doAsyncTask() throws InterruptedException {

         // 假设执行一个很耗时的任务

         Thread.sleep( 10 * 1000 );

         System.out.println( "执行完成,我执行了10秒" );

     }

}

创建spring配置AppConfig

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

/**

  * spring 配置

  *

  * @author Peng

  */

@Configuration

@EnableAsync

public class AppConfig {

     /**

      * 声明异步任务bean

      *

      * @return

      */

     @Bean

     public AsyncTask asyncTask() {

         return new AsyncTask();

     }

}

测试

?

1

2

3

4

5

6

7

8

9

10

11

12

13

/**

  * 异步测试

  *

  * @author Peng

  */

public class AppTest {

     public static void main(String[] args) throws InterruptedException {

         ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig. class );

         AsyncTask task = ctx.getBean(AsyncTask. class );

         task.doAsyncTask();

         System.out.println( "异步任务调用成功,返回客户端执行成功,异步任务继续执行" );

     }

}

执行结果

异步任务调用成功,返回客户端执行成功,异步任务继续执行

执行完成,我执行了10秒

从结果可以看出,异步任务测试成功!

Spring @Async Demo

模拟一个业务场景:系统新用户注册成功后,异步发送邮件。

Project Directory

Maven Dependency

?

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

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

<? xml version = "1.0" encoding = "UTF-8" ?>

< project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://HdhCmsTestw3.org/2001/XMLSchema-instance"

     xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" >

     < modelVersion >4.0.0</ modelVersion >

     < groupId >org.fool.springasync</ groupId >

     < artifactId >springasync</ artifactId >

     < name >springasync</ name >

     < packaging >war</ packaging >

     < version >1.0.0-BUILD-SNAPSHOT</ version >

     < properties >

         < org.springframework-version >4.2.8.RELEASE</ org.springframework-version >

     </ properties >

     < dependencies >

         <!-- Spring -->

         < dependency >

             < groupId >org.springframework</ groupId >

             < artifactId >spring-context</ artifactId >

             < version >${org.springframework-version}</ version >

         </ dependency >

         < dependency >

             < groupId >org.springframework</ groupId >

             < artifactId >spring-webmvc</ artifactId >

             < version >${org.springframework-version}</ version >

         </ dependency >

         < dependency >

             < groupId >com.fasterxml.jackson.core</ groupId >

             < artifactId >jackson-databind</ artifactId >

             < version >2.8.1</ version >

         </ dependency >

         < dependency >

             < groupId >com.google.guava</ groupId >

             < artifactId >guava</ artifactId >

             < version >19.0</ version >

         </ dependency >

         < dependency >

             < groupId >org.apache测试数据mons</ groupId >

             < artifactId >commons-lang3</ artifactId >

             < version >3.4</ version >

         </ dependency >

         <!-- @Inject -->

         < dependency >

             < groupId >javax.inject</ groupId >

             < artifactId >javax.inject</ artifactId >

             < version >1</ version >

         </ dependency >

         <!-- Servlet -->

         < dependency >

             < groupId >javax.servlet</ groupId >

             < artifactId >javax.servlet-api</ artifactId >

             < version >3.1.0</ version >

             < scope >provided</ scope >

         </ dependency >

         < dependency >

             < groupId >javax.servlet.jsp</ groupId >

             < artifactId >javax.servlet.jsp-api</ artifactId >

             < version >2.3.1</ version >

             < scope >provided</ scope >

         </ dependency >

         < dependency >

             < groupId >javax.servlet</ groupId >

             < artifactId >jstl</ artifactId >

             < version >1.2</ version >

         </ dependency >

         <!-- Test -->

         < dependency >

             < groupId >junit</ groupId >

             < artifactId >junit</ artifactId >

             < version >4.12</ version >

             < scope >test</ scope >

         </ dependency >

     </ dependencies >

     < build >

         < plugins >

             < plugin >

                 < groupId >org.apache.maven.plugins</ groupId >

                 < artifactId >maven-eclipse-plugin</ artifactId >

                 < version >2.10</ version >

                 < configuration >

                     < additionalProjectnatures >

                         < projectnature >org.springframework.ide.eclipse.core.springnature</ projectnature >

                     </ additionalProjectnatures >

                     < additionalBuildcommands >

                         < buildcommand >org.springframework.ide.eclipse.core.springbuilder</ buildcommand >

                     </ additionalBuildcommands >

                     < downloadSources >true</ downloadSources >

                     < downloadJavadocs >true</ downloadJavadocs >

                 </ configuration >

             </ plugin >

             < plugin >

                 < groupId >org.apache.maven.plugins</ groupId >

                 < artifactId >maven-compiler-plugin</ artifactId >

                 < version >3.5.1</ version >

                 < configuration >

                     < source >1.8</ source >

                     < target >1.8</ target >

                     < compilerArgument >-Xlint:all</ compilerArgument >

                     < showWarnings >true</ showWarnings >

                     < showDeprecation >true</ showDeprecation >

                 </ configuration >

             </ plugin >

             < plugin >

                 < groupId >org.eclipse.jetty</ groupId >

                 < artifactId >jetty-maven-plugin</ artifactId >

                 < version >9.3.11.v20160721</ version >

                 < configuration >

                     < scanIntervalSeconds >10</ scanIntervalSeconds >

                     < httpConnector >

                         < port >8888</ port >

                     </ httpConnector >

                     < webApp >

                         < contextPath >/springasync</ contextPath >

                     </ webApp >

                 </ configuration >

             </ plugin >

         </ plugins >

     </ build >

</ project >

web.xml

?

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

<? xml version = "1.0" encoding = "UTF-8" ?>

< web-app xmlns:xsi = "http://HdhCmsTestw3.org/2001/XMLSchema-instance" xmlns = "http://java.sun测试数据/xml/ns/javaee"

     xmlns:web = "http://java.sun测试数据/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation = "http://java.sun测试数据/xml/ns/javaee http://java.sun测试数据/xml/ns/javaee/web-app_3_0.xsd"

     id = "WebApp_ID" version = "3.0" >

     <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->

     < context-param >

         < param-name >contextConfigLocation</ param-name >

         < param-value >/WEB-INF/spring/root-context.xml</ param-value >

     </ context-param >

     <!-- Creates the Spring Container shared by all Servlets and Filters -->

     < listener >

         < listener-class >org.springframework.web.context.ContextLoaderListener</ listener-class >

     </ listener >

     <!-- Processes application requests -->

     < servlet >

         < servlet-name >appServlet</ servlet-name >

         < servlet-class >org.springframework.web.servlet.DispatcherServlet</ servlet-class >

         < init-param >

             < param-name >contextConfigLocation</ param-name >

             < param-value >/WEB-INF/spring/appServlet/servlet-context.xml</ param-value >

         </ init-param >

         < load-on-startup >1</ load-on-startup >

     </ servlet >

     < servlet-mapping >

         < servlet-name >appServlet</ servlet-name >

         < url-pattern >/</ url-pattern >

     </ servlet-mapping >

</ web-app >

root-context.xml

?

1

2

3

4

5

6

7

<? xml version = "1.0" encoding = "UTF-8" ?>

< beans xmlns = "http://HdhCmsTestspringframework.org/schema/beans"

     xmlns:xsi = "http://HdhCmsTestw3.org/2001/XMLSchema-instance"

     xsi:schemaLocation = "http://HdhCmsTestspringframework.org/schema/beans http://HdhCmsTestspringframework.org/schema/beans/spring-beans.xsd" >

    

     <!-- Root Context: defines shared resources visible to all other web components -->       

</ beans >

servlet-context.xml

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

<? xml version = "1.0" encoding = "UTF-8" ?>

< beans:beans xmlns = "http://HdhCmsTestspringframework.org/schema/mvc" xmlns:xsi = "http://HdhCmsTestw3.org/2001/XMLSchema-instance"

     xmlns:beans = "http://HdhCmsTestspringframework.org/schema/beans" xmlns:context = "http://HdhCmsTestspringframework.org/schema/context"

     xmlns:task = "http://HdhCmsTestspringframework.org/schema/task"

     xsi:schemaLocation="http://HdhCmsTestspringframework.org/schema/mvc http://HdhCmsTestspringframework.org/schema/mvc/spring-mvc.xsd

         http://HdhCmsTestspringframework.org/schema/beans http://HdhCmsTestspringframework.org/schema/beans/spring-beans.xsd

         http://HdhCmsTestspringframework.org/schema/context http://HdhCmsTestspringframework.org/schema/context/spring-context.xsd

         http://HdhCmsTestspringframework.org/schema/task http://HdhCmsTestspringframework.org/schema/task/spring-task.xsd">

     <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    

     <!-- Enables the Spring MVC @Controller programming model -->

     < annotation-driven />

     <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources

         directory -->

     < resources mapping = "/resources/**" location = "/resources/" />

     <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->

     < beans:bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" >

         < beans:property name = "prefix" value = "/WEB-INF/views/" />

         < beans:property name = "suffix" value = ".jsp" />

     </ beans:bean >

     < context:component-scan base-package = "org.fool.springasync" />

</ beans:beans >

AsyncConfig.java

?

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

44

45

46

47

48

49

50

package org.fool.springasync;

import java.util.concurrent.Executor;

import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.PropertySource;

import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

import org.springframework.scheduling.annotation.EnableAsync;

import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

 

@Configuration

@EnableAsync

@PropertySource ( "classpath:async.properties" )

public class AsyncConfig {

     /** Set the ThreadPoolExecutor's core pool size. */

     @Value ( "${core.pool.size}" )

     private Integer corePoolSize;

    

     /** Set the ThreadPoolExecutor's maximum pool size. */

     @Value ( "${max.pool.size}" )

     private Integer maxPoolSize;

    

     /** Set the capacity for the ThreadPoolExecutor's BlockingQueue. */

     @Value ( "${queue.capacity}" )

     private Integer queueCapacity; 

  

     @Value ( "${thread.name.prefix}" )

     private String ThreadNamePrefix;

    

     @Bean

     public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfig() { 

         return new PropertySourcesPlaceholderConfigurer(); 

     }

    

     @Bean

     public Executor getAsyncExecutor() { 

         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 

         executor.setCorePoolSize(corePoolSize); 

         executor.setMaxPoolSize(maxPoolSize); 

         executor.setQueueCapacity(queueCapacity); 

         executor.setThreadNamePrefix(ThreadNamePrefix); 

  

         // rejection-policy:当pool已经达到max size的时候,如何处理新任务 

         // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 

         executor.setRejectedExecutionHandler( new ThreadPoolExecutor.CallerRunsPolicy()); 

         executor.initialize();        

         return executor; 

     }

}

Note:

AsyncConfig使用Annotation进行Spring Async的配置,当然也可以用XML的方式进行配置,只需要在servlet-context.xml中添加task的命名空间,同时加下如下两行配置:

?

1

2

3

<!-- Enables Spring Async -->

< task:annotation-driven executor = "asyncExecutor" />

< task:executor id = "asyncExecutor" pool-size = "2-4" queue-capacity = "10" />

<task:executor />配置参数:

id: 当配置多个executor时,被@Async("id")指定使用;也被作为线程名的前缀。

pool-size:

core size:最小的线程数,缺省:1 max size:最大的线程数,缺省:Integer.MAX_VALUE

queue-capacity: 当最小的线程数已经被占用满后,新的任务会被放进queue里面,当这个queue的capacity也被占满之后,pool里面会创建新线程处理这个任务,直到总线程数达到了max size,这时系统会拒绝这个任务并抛出TaskRejectedException异常(缺省配置的情况下,可以通过rejection-policy来决定如何处理这种情况)。缺省值为:Integer.MAX_VALUE

keep-alive: 超过core size的那些线程,任务完成后,再经过这个时长(秒)会被结束掉

rejection-policy: 当pool已经达到max size的时候,如何处理新任务

ABORT(缺省):抛出TaskRejectedException异常,然后不执行 DISCARD:不执行,也不抛出异常 DISCARD_OLDEST:丢弃queue中最旧的那个任务 CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行

MailService.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

package org.fool.springasync;

import org.springframework.scheduling.annotation.Async;

import org.springframework.stereotype.Component;

@Component

public class MailService {

 

     @Async

     public void sendMail(String username) {

         System.out.println( "Send Mail initialization..." );

         System.out.println( "Execute method asynchronously - " + Thread.currentThread().getName());

 

         try {

             Thread.sleep( 5000 );

             System.out.println( "Welcome " + username);

         } catch (InterruptedException e) {

             e.printStackTrace();

         }

 

         System.out.println( "Send Mail Async done!!!" );

     }

}

User.java

?

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

44

45

package org.fool.springasync;

import org.apache测试数据mons.lang3.builder.ToStringBuilder;

import org.apache测试数据mons.lang3.builder.ToStringStyle;

public class User {

     private Long id;

     private String username;

     private String password;

     public User() {

     }

 

     public User(Long id, String username, String password) {

         this .id = id;

         this .username = username;

         this .password = password;

     }

 

     public Long getId() {

         return id;

     }

 

     public void setId(Long id) {

         this .id = id;

     }

 

     public String getUsername() {

         return username;

     }

 

     public void setUsername(String username) {

         this .username = username;

     }

 

     public String getPassword() {

         return password;

     }

 

     public void setPassword(String password) {

         this .password = password;

     }

 

     @Override

     public String toString() {

         return ToStringBuilder.reflectionToString( this , ToStringStyle.SHORT_PREFIX_STYLE);

     }

}

UserService.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

package org.fool.springasync;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

@Service

public class UserService { 

     @Inject

     private MailService mailService;   

     public void registerUser(User user) {

         System.out.println( "insert user to db..." );

         mailService.sendMail(user.getUsername());

         System.out.println( "register done, please check the email later!!!" );

     }  

}

UserController.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

package org.fool.springasync;

import javax.inject.Inject;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.ResponseBody;

 

@Controller

@RequestMapping ( "/user" )

public class UserController {  

     @Inject

     private UserService userService;   

     @RequestMapping (value = "/testasync" , method = RequestMethod.POST)

     @ResponseBody

     public User register( @RequestBody User user) {

         System.out.println(user);      

         userService.registerUser(user);    

         return user;

     }

}

Test

http://localhost:8888/springasync/user/testasync

POST请求(send两次)

Console Output

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://retry.blog.csdn.net/article/details/79014329

查看更多关于使用Spring开启@Async异步方式(javaconfig配置)的详细内容...

  阅读:21次