针对“浅谈Spring @Async异步线程池用法总结”的主题,我将详细讲解如下:
1. 什么是Spring @Async异步线程池
在介绍 Spring @Async 异步线程池之前,我们需要先了解同步和异步的概念:
- 同步:就是一个任务执行完之后再执行下一个任务,任务按顺序一个接一个依次执行。
- 异步:与同步相反,异步任务的执行时间和顺序是不可预测的,任务的执行不会像同步任务那样阻塞调用者线程,而是在后台以另一个线程并行的方式来执行。
Spring @Async异步线程池是Spring框架提供的一种异步调用方式,它通过配置一个线程池来异步执行被 @Async 标记的方法,以避免阻塞主线程。在使用 Spring @Async 时,需要满足以下条件:
- 被 @Async 标记的方法必须在 public 方法;
- 被 @Async 标记的方法必须在类本身被调用,不能通过 this 对象进行调用,以避免 AOP 的失效;
- 被 @Async 标记的方法不能有返回值或抛出异常,因为被调用方法是在异步线程中执行的,异步线程无法将结果返回给调用线程。
2. Spring @Async异步线程池的用法
在使用 Spring @Async 异步线程池时,需要完成以下步骤:
2.1. 配置异步线程池
首先需要配置异步线程池的 Bean,可以通过在配置类上添加 @EnableAsync
注解来开启 Spring 的异步处理功能,配置类的方法上使用 @Async
注解来标识该方法是异步方法,如下所示:
@Configuration
@EnableAsync
public class AppConfig {
@Bean(name = "asyncExecutor")
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(10);
executor.setThreadNamePrefix("asyncExecutor-");
executor.initialize();
return executor;
}
}
上述代码通过 @EnableAsync
注解开启 Spring 的异步处理功能,同时通过 asyncExecutor()
方法配置了一个核心线程池大小为 10,最大线程池大小为 100 的异步线程池。
2.2. 标记异步方法
在需要异步执行的方法上添加 @Async
注解,如下所示:
@Service
public class TestService {
@Async("asyncExecutor")
public void asyncMethod() {
System.out.println("异步方法执行开始...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步方法执行结束...");
}
}
上述代码中方法 asyncMethod()
被 @Async("asyncExecutor")
注解标记,表示该方法在 asyncExecutor
配置的异步线程池中执行。
3. 调用异步方法
最后在需要调用异步方法的地方使用 Spring 的 ApplicationContext
获取 TestService
的 Bean,然后通过 Bean 调用异步方法即可,如下所示:
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
TestService testService = context.getBean(TestService.class);
testService.asyncMethod();
System.out.println("调用结束...");
}
上述代码中,我们获取了 TestService
的 Bean,并通过该 Bean 调用了异步方法 asyncMethod()
。
3. 异步线程池的使用注意事项
使用 Spring @Async 异步线程池也有一些注意事项,大概总结如下:
- 避免使用方法本身中的静态变量和单例类中的静态变量,这些变量可能在多个线程之间冲突;
- Spring 的 AOP 技术是通过 JDK 动态代理或 CGLIB 动态代理实现的,而 JDK 动态代理只能代理接口方法,因此被 @Async 注解的方法必须是在接口方法上定义的,否则 Spring 将无法创建代理对象,从而无法实现异步调用;
- 被 @Async 注解标记的方法应该是轻量级的,可以通过阻止主线程来释放CPU时间片。
4. 示例说明
下面提供两个简单的示例说明 Spring @Async 异步线程池的用法。
示例1:
在 AppConfig.java
中配置异步线程池:
@Configuration
@EnableAsync
public class AppConfig {
@Bean(name = "asyncExecutor")
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(10);
executor.setThreadNamePrefix("asyncExecutor-");
executor.initialize();
return executor;
}
}
定义一个 Service 类 TestService.java
,在该类中定义一个异步方法 asyncMethod()
:
@Service
public class TestService {
@Async("asyncExecutor")
public void asyncMethod() {
System.out.println("异步方法执行开始...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步方法执行结束...");
}
}
在 Main.java
中获取 TestService
的 Bean,调用异步方法:
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
TestService testService = context.getBean(TestService.class);
testService.asyncMethod();
System.out.println("调用结束...");
}
输出结果为:
调用结束...
异步方法执行开始...
示例2:
在 AppConfig.java
中配置异步线程池:
@Configuration
@EnableAsync
public class AppConfig2 {
@Bean(name = "asyncExecutor")
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(10);
executor.setThreadNamePrefix("asyncExecutor-");
executor.initialize();
return executor;
}
}
定义一个 Controller 类 TestController.java
,在该类中定义一个异步方法 doAsync()
:
@RestController
public class TestController {
@Autowired
private TestService testService;
@RequestMapping("/doAsync")
public void doAsync() {
testService.asyncMethod();
}
}
在 Main.java
中启动 Spring Boot 应用:
@SpringBootApplication(scanBasePackages = "com.example.demo")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
访问 url http://localhost:8080/doAsync
,控制台输出结果为:
异步方法执行结束...
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈Spring @Async异步线程池用法总结 - Python技术站