news 2026/9/28 15:11:48

Spring Boot 异步

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot 异步

当某个请求执行非常耗时,当有大量访问该请求的时候,再访问请求其他服务时,会出现没有连接使用的情况。造成这种现象的主要原因是,容器中线程的数量是一定的,如果当所有线程都正在用来处理请求服务的时候,再有请求进来就没有多余的连接可用,只能拒绝连接。

SpringBoot异步机制可以使请求到了controller的时候,容器中的线程直接返回,同时使用系统内部的线程来执行耗时的服务,处理结束后果再将请求返回给客户端。

Servlet 3.0 新增了请求的异步处理,Spring 3.2 也在此基础上做了封装处理。
Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程。使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor。

在 Spring Boot 框架中,可以在配置类中添加@EnableAsync开始对异步任务的支持,并将相应的方法使用@Async注解来声明为一个异步任务。

对于@Transactional、@Async等注解,Spring扫描到具有这些注解方法的类时,生成一个代理类,由代理类去执行,所以异步方法必须在类外部调用,并且@Async所修饰的不能是static方法。获取得到执行结果则可设置异步函数返回类型为Future

@Component public class MyAsyncTask { @Async public Future<String> task1() throws InterruptedException{ return new AsyncResult<String>("task1执行完毕"); }

Controller的方法可以很快返回一个java.util.concurrent.Callable或DeferredResult,同时Servlet容器的主线程退出和释放,这并不意味着客户端收到了一个响应。

//Callable @Controller public class DefaultController { @RequestMapping("/async/test") @ResponseBody public Callable<String> callable() { //调用后生成一个非web线程来执行部分代码。 return new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(3 * 1000L); return "finish" + System.currentTimeMillis(); } }; } } //DeferredResult @RestController public class AsyncDeferredController { private final TaskService taskService; @Autowired public AsyncDeferredController(TaskService taskService) { this.taskService = taskService; } @RequestMapping(value = "/deferred", method = RequestMethod.GET, produces = "text/html") public DeferredResult<String> executeSlowTask() { DeferredResult<String> deferredResult = new DeferredResult<>(); CompletableFuture.supplyAsync(taskService::execute).whenCompleteAsync((result, throwable) -> deferredResult.setResult(result)); return deferredResult; } }

Callable的其它示例:

public static void main(String[] args) throws ExecutionException, InterruptedException { Callable<String> callable = new CallableImpl("my callable test!"); FutureTask<String> task = new FutureTask<>(callable); new Thread(task).start(); //调用get()会阻塞主线程。 String result = task.get(); }

Callable和DeferredResult的区别:

Callable和DeferredResult效果都是释放容器线程,在另一个线程中运行长时间的任务。

不同的是谁管理执行任务的线程:

  • Callable在执行线程完毕时返回。
  • Deferredresult是通过设置返回对象值返回,可以在任何地方控制返回。


定时任务


1.在程序入口类上添加类注解 @EnableScheduling 来启用计划任务
2.在定时任务的类上加上类注解 @Component,在具体的定时任务方法上加上注解 @Scheduled 启动该定时任务。

@Scheduled(initialDelay=10000, fixedDelay=10000) //10 seconds, or use cron express

默认所有的@Scheduled都是串行执行的,并行需要继承SchedulingConfigurer类并重写其方法,实现并行任务。

@Configuration @EnableScheduling public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskExecutor()); } @Bean(destroyMethod="shutdown") public Executor taskExecutor() { return Executors.newScheduledThreadPool(100); } }

当某个请求执行非常耗时,当有大量访问该请求的时候,再访问请求其他服务时,会出现没有连接使用的情况。造成这种现象的主要原因是,容器中线程的数量是一定的,例如500个,当这500个线程都正在用来处理请求服务的时候,再有请求进来,没有多余的连接可用了,只能拒绝连接。

SpringBoot异步机制可以使请求到controller中时,容器线程直接返回,同时使用系统内部的线程来执行耗时的服务,处理结束后果再将请求返回给客户端。

Servlet 3.0 新增了请求的异步处理,Spring 3.2 也在此基础上做了封装处理。
Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程。使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor。

在 Spring Boot 框架中,可以在配置类中添加@EnableAsync开始对异步任务的支持,并将相应的方法使用@Async注解来声明为一个异步任务。

对于@Transactional、@Async等注解,spring扫描时具有这些注解方法的类时,生成一个代理类,由代理类去执行,所以异步方法必须在类外部调用,并且@Async所修饰的不能是static方法。获取得到执行结果则可设置异步函数返回类型为Future。
<pre>
@Component
public class MyAsyncTask {
@Async
public Future<String> task1() throws InterruptedException{
return new AsyncResult<String>("task1执行完毕");
}
</pre>

Controller的方法可以很快返回一个java.util.concurrent.Callable或Deferredresult,同时Servlet容器的主线程退出和释放,这并不意味着客户端收到了一个响应。
<pre>
//Callable
@Controller
public class DefaultController {
@RequestMapping("/async/test")
@ResponseBody
public Callable<String> callable() {
//调用后生成一个非web线程来执行部分代码。
return new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(3 * 1000L);
return "finish" + System.currentTimeMillis();
}
};
}
}

//DeferredResult
@RestController
public class AsyncDeferredController {
private final TaskService taskService;

@Autowired
public AsyncDeferredController(TaskService taskService) {
this.taskService = taskService;
}

@RequestMapping(value = "/deferred", method = RequestMethod.GET, produces = "text/html")
public DeferredResult<String> executeSlowTask() {
DeferredResult<String> deferredResult = new DeferredResult<>();
CompletableFuture.supplyAsync(taskService::execute).whenCompleteAsync((result, throwable) -> deferredResult.setResult(result));

return deferredResult;
}
}
</pre>

Callable的其它示例:
<pre>
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<String> callable = new CallableImpl("my callable test!");
FutureTask<String> task = new FutureTask<>(callable);
new Thread(task).start();
//调用get()会阻塞主线程。
String result = task.get();
}
</pre>

Callable和Deferredresult的区别:
Callable和Deferredresult效果都是释放容器线程,在另一个线程中运行长时间的任务。不同的是谁管理执行任务的线程:Callable在执行线程完毕时返回;Deferredresult是通过设置返回对象值返回,可以在任何地方控制返回。

https://blog.csdn.net/he90227/article/details/52262163
Spring MVC 异步处理请求,提高程序性能
<h1>定时任务</h1>
1.在程序入口类上添加类注解 @EnableScheduling 来启用计划任务
2.在定时任务的类上加上类注解 @Component,在具体的定时任务方法上加上注解 @Scheduled 启动该定时任务。
@Scheduled(initialDelay=10000, fixedDelay=10000) //10 seconds, or use cron express

默认所有的@Scheduled都是串行执行的,并行需要继承SchedulingConfigurer类并重写其方法,实现并行任务。
<pre>
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}

@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(100);
}
}
</pre>
详解SpringBoot Schedule配置
http://www.cfei.net/archives/88832

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 15:11:29

Nginx高性能轻量级服务器:从原理到配置实战详解

在接触Nginx之前&#xff0c;我一直觉得“服务器”是个特别沉重的词——动辄几G的内存占用&#xff0c;复杂到翻文档翻到头秃的配置&#xff0c;还有莫名其妙的高并发瓶颈。直到项目里第一次被大量并发请求压垮&#xff0c;我才认真去研究Nginx&#xff0c;结果发现很多过去靠堆…

作者头像 李华
网站建设 2026/9/28 15:09:01

用pygame打造会唱歌的全屏回忆相册:零基础Python项目

直接说结论&#xff1a;这是一个零基础也能照着手敲出来的 Python 小项目——用 pygame 做一个全屏播放的回忆相册&#xff0c;每张照片配上专属背景音乐&#xff0c;按一下空格键&#xff0c;一颗心形烟花就在屏幕中间炸开。做完之后还能打包成 exe 发给对方&#xff0c;不需要…

作者头像 李华
网站建设 2026/9/28 15:08:56

从AI代码评审到智能体底座:开发者效率工具与内容实战解析

又到了例行翻 GitHub 的时间。2026 年第 38 周这期周刊&#xff0c;我本来只是想随便扫一眼&#xff0c;结果发现了好几个值得单独拉出来聊一聊的项目&#xff1a;阿里把内部代码评审工具开源了&#xff0c;有人在做 ADHD&#xff08;注意力缺陷多动障碍&#xff09;友好的内容…

作者头像 李华
网站建设 2026/9/28 15:08:35

SVM在电网负荷预测中的应用:从原理到调参避坑全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 15:07:49

AI整理教学资料全流程:从散装课件到教案PPT的实战方法论

最近帮一位老师朋友处理课程资料&#xff0c;她手头有七八个版本的教学课件、课程设计文档、历年考卷、甚至还有几张手机拍的白板照片。这些资料都很全&#xff0c;但彼此之间完全没有统一结构&#xff0c;标准的“散装”状态。她想把这些东西整理成一份能直接用的教案&#xf…

作者头像 李华