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

网友投稿 272 2022-12-14

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

目录Spring开启@Async异步(javaconfig配置)应用场景创建AsyncTask创建spring配置AppConfig测试Spring @Async Demo

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

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

应用场景

某些耗时较长的而用户不需要等待该方法的处理结果

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

代码

创建AsyncTask

/**

* 异步任务

*

* @author Peng

*/

public class AsyncTask {

@Async

public void doAsyncTask() throws InterruptedException {

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

Thread.sleep(10 * 1000);

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

}

}

创建spring配置AppConfig

/**

* spring 配置

*

* @author Peng

*/

@Configuration

@EnableAsync

public class AppConfig {

/**

* 声明异步任务bean

*

* @return

*/

@Bean

public AsyncTask asyncTask() {

return new AsyncTask();

}

}

测试

/**

* 异步测试

*

* @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

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

4.0.0

org.fool.springasync

springasync

springasync

war

1.0.0-BUILD-SNAPSHOT

4.2.8.RELEASE

org.springframework

spring-context

${org.springframework-version}

org.springframework

spring-webmvc

${org.springframework-version}

com.fasterxml.jackson.core

jackson-databind

2.8.1

com.google.guava

guava

19.0

org.apache.commons

commons-lang3

3.4

javax.inject

javax.inject

1

javax.servlet

javax.servlet-api

3.1.0

provided

javax.servlet.jsp

javax.servlet.jsp-api

2.3.1

provided

javaxhttp://.servlet

jstl

1.2

junit

junit

4.12

test

org.apache.maven.plugins

maven-eclipse-plugin

2.10

org.springframework.ide.eclipse.core.springnature

org.springframework.ide.eclipse.core.springbuilder

true

true

org.apache.maven.plugins

maven-compiler-plugin

3.5.1

1.8

1.8

-Xlint:all

true

true

org.eclipse.jetty

jetty-maven-plugin

9.3.11.v20160721

10

8888

/springasync

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

4.0.0

org.fool.springasync

springasync

springasync

war

1.0.0-BUILD-SNAPSHOT

4.2.8.RELEASE

org.springframework

spring-context

${org.springframework-version}

org.springframework

spring-webmvc

${org.springframework-version}

com.fasterxml.jackson.core

jackson-databind

2.8.1

com.google.guava

guava

19.0

org.apache.commons

commons-lang3

3.4

javax.inject

javax.inject

1

javax.servlet

javax.servlet-api

3.1.0

provided

javax.servlet.jsp

javax.servlet.jsp-api

2.3.1

provided

javaxhttp://.servlet

jstl

1.2

junit

junit

4.12

test

org.apache.maven.plugins

maven-eclipse-plugin

2.10

org.springframework.ide.eclipse.core.springnature

org.springframework.ide.eclipse.core.springbuilder

true

true

org.apache.maven.plugins

maven-compiler-plugin

3.5.1

1.8

1.8

-Xlint:all

true

true

org.eclipse.jetty

jetty-maven-plugin

9.3.11.v20160721

10

8888

/springasync

web.xml

xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

id="WebApp_ID" version="3.0">

contextConfigLocation

/WEB-INF/spring/root-context.xml

org.springframework.web.context.ContextLoaderListener

appServlet

org.springframework.web.servlet.DispatcherServlet

contextConfigLocation

/WEB-INF/spring/appServlet/servlet-context.xml

1

appServlet

/

xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

id="WebApp_ID" version="3.0">

contextConfigLocation

/WEB-INF/spring/root-context.xml

org.springframework.web.context.ContextLoaderListener

appServlet

org.springframework.web.servlet.DispatcherServlet

contextConfigLocation

/WEB-INF/spring/appServlet/servlet-context.xml

1

appServlet

/

root-context.xml

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

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

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

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

servlet-context.xml

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

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

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

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

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

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

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

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

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

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

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

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

AsyncConfig.java

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的命名空间,同时加下如下两行配置:

配置参数:

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

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

package org.fool.springasync;

import org.apache.commons.lang3.builder.ToStringBuilder;

import org.apache.commons.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

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

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

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java 线程的优先级(setPriority)案例详解
下一篇:Java面试题冲刺第二十五天
相关文章

 发表评论

暂时没有评论,来抢沙发吧~