网站首页 > 技术文章 正文
环境:Spring5.3.23
上一篇:《Spring强大的任务执行与调度》
Springboot中配置
如果上下文中没有 Executor bean, Spring Boot会用合理的默认值自动配置ThreadPoolTaskExecutor,它可以自动关联到异步任务执行(@EnableAsync)和Spring MVC异步请求处理。
如果你在上下文中定义了自定义 Executor,常规任务执行(例如@EnableAsync)会透明地使用它,但Spring MVC(异步处理)支持不会配置它,因为它需要AsyncTaskExecutor实现(名为applicationTaskExecutor)。根据目标安排,可以将你的Executor更改为ThreadPoolTaskExecutor,或者同时定义一个ThreadPoolTaskExecutor和一个包装自定义执行器的AsyncConfigurer。
自动配置的TaskExecutorBuilder让你可以轻松地创建实例,重现自动配置默认做的事情。
线程池使用8个核心线程,这些线程可以根据负载大小增减。这些默认设置可以使用spring.task.execution命名空间进行微调,如下面的例子所示。
spring:
task:
execution:
pool:
max-size: 16
queue-capacity: 100
keep-alive: "10s"
这将修改线程池,使用有界队列,以便在队列满时(100个任务),线程池增加到最多16个线程。当线程空闲10秒(而不是默认的60秒)时,会回收线程,因此池的收缩会更积极。
如果需要关联到计划任务执行,ThreadPoolTaskScheduler也可以自动配置(例如@EnableScheduling)。线程池默认使用一个线程,可以使用spring.task.scheduling命名空间对其设置进行微调,如下面的例子所示:
spring:
task:
scheduling:
thread-name-prefix: "scheduling-"
pool:
size: 2
如果需要创建自定义的执行器或调度器,TaskExecutorBuilder bean和TaskSchedulerBuilder bean都可以在上下文中使用。
Spring配置
- 启用功能
@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {
}
- @Scheduled注解
通过给方法添加@Scheduled注解,以及触发器元数据。例如,下面的方法以固定的延迟每5秒(5000毫秒)调用一次,这意味着周期是从前面每次调用的完成时间计算出来的。
@Scheduled(fixedDelay = 5000)
public void doSomething() {
}
默认情况下,毫秒将被用作固定延迟、固定速率和初始延迟值的时间单位。如果你想使用不同的时间单位,比如秒或分钟,可以通过@Scheduled中的timeUnit属性进行配置。
@Scheduled(fixedDelay = 5, timeUnit = TimeUnit.SECONDS)
public void doSomething() {
}
如果需要固定速率的执行,可以在注释中使用fixedRate属性。下面的方法每5秒调用一次(在每次调用的连续开始时间之间测量)。
@Scheduled(fixedRate = 5, timeUnit = TimeUnit.SECONDS)
public void doSomething() {
}
对于固定延迟和固定速率的任务,你可以通过指定第一次执行方法之前等待的时间来指定初始延迟,如下面的fixedRate示例所示。
@Scheduled(initialDelay = 1000, fixedRate = 5000)
public void doSomething() {
}
如果简单的周期性调度表达能力不够,可以提供一个cron表达式。下面的例子只在工作日运行:
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
}
从Spring Framework 4.3开始,任何作用域的bean都支持@Scheduled方法。
确保没有在运行时初始化同一个@Scheduled注解类的多个实例,除非你确实希望为每个此类实例安排回调。与此相关,请确保不要在带有@Scheduled注解并在容器中注册为常规Spring bean的bean类上使用@Configurable。否则,就会得到两次初始化(一次通过容器,一次通过@Configurable方面),每个@Scheduled方法都会被调用两次。
- @Async注解
你可以为方法提供@Async注解,以便异步调用该方法。换句话说,调用者在调用后立即返回,而该方法的实际执行发生在已提交给Spring TaskExecutor的任务中。在最简单的情况下,可以把注解应用到返回void的方法上,如下面的例子所示:
@Async
void doSomething() {
}
与使用@Scheduled注解的方法不同,这些方法可以接收参数,因为它们是在运行时由调用者以“正常”方式调用的,而不是从容器管理的计划任务中调用的。例如,下面的代码就是@Async注解的合法应用:
@Async
void doSomething(String s) {
}
即使是有返回值的方法也可以异步调用。然而,这种方法的返回值必须是future类型的。这仍然提供了异步执行的好处,因此调用者可以在调用get()之前执行其他任务。下面的例子展示了如何在返回值的方法上使用@Async:
@Async
Future<String> returnSomething(int i) {
}
@Async方法不仅可以声明常规的java.util.concurrent.Future返回类型,还可以声明Spring的org.springframework.util.concurrent.ListenableFuture,或者从Spring 4.2开始,JDK 8的java.util.concurrent.CompletableFuture可以与异步任务进行更丰富的交互,也可以与进一步的处理步骤立即组合。
你不能将@Async与@PostConstruct这样的生命周期回调结合使用。要异步初始化Spring bean,当前必须使用一个单独的初始化Spring bean,然后在目标上调用@Async注解方法,如下面的例子所示。
public class SampleBeanImpl implements SampleBean {
@Async
void doSomething() {
}
}
public class SampleBeanInitializer {
private final SampleBean bean;
public SampleBeanInitializer(SampleBean bean) {
this.bean = bean;
}
@PostConstruct
public void initialize() {
bean.doSomething();
}
}
- 使用@Async对执行器进行限定
默认情况下,当在方法上指定@Async时,使用的执行器是启用async支持时配置的执行器,即“注解驱动”元素(如果使用XML或AsyncConfigurer实现的话)。不过,如果需要在执行给定方法时指定默认执行器以外的执行器,可以使用@Async注解的value属性。如下面的例子所示:
@Async("otherExecutor")
void doSomething(String s) {
}
- 使用@Async管理异常
当@Async方法有Future类型的返回值时,管理方法执行期间抛出的异常很容易,因为这个异常是在对Future的结果调用get方法时抛出的。然而,如果返回类型为void,则异常不会被捕获,无法传输。你可以提供一个AsyncUncaughtExceptionHandler来处理这种异常。如下面的例子所示:
public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
}
}
完毕!!!
关注我长期更新
SpringBoot对Spring MVC都做了哪些事?(一)
SpringBoot对Spring MVC都做了哪些事?(二)
SpringBoot对Spring MVC都做了哪些事?(三)
SpringBoot对Spring MVC都做了哪些事?(四)
Spring Retry重试框架的应用
spring data jpa 高级应用
Spring MVC 异常处理方式
Spring容器这些扩展点你都清楚了吗?
Spring MVC 异步请求方式
Spring事务实现原理源码分析
Spring中的@Configuration注解你真的了解吗?
Spring 强大的数据验证功能
Spring容器这些扩展点你都清楚了吗?
Spring是如何解决循环依赖的?
猜你喜欢
- 2024-12-12 Spring中ThreadPoolTaskExecutor 线程池的使用进阶
- 2024-12-12 springboot定时任务防止多实例重复执行架构方案的实现
- 2024-12-12 springboot-多数据源-使用详解
- 2024-12-12 字节面试官:“这35道 Spring Cloud 面试题都答不上来?”
- 2024-12-12 SpringBoot自定义线程池(ThreadPoolTaskExecutor)
- 2024-12-12 你不知道的Spring定时任务
- 2024-12-12 springboot整合xxl-job分布式定时任务
- 2024-12-12 如何将Spring Cloud Task发布Data Flow上执行?
- 2024-12-12 详细介绍一下Spring Boot项目中如何使用定时任务操作?
- 2024-12-12 Spring Task 执行长耗时的任务时,会堆集并行执行吗?
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- c语言min函数头文件 (77)
- asynccallback (87)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 无效的列索引 (74)