java中@Async异步调用的方法
前言
异步调用与同步调用
同步调用:顺序执行,通过调用返回结果再次执行下一个调用
异步调用:通过调用,无需等待返回结果,执行下一个调用
1. @Async讲解
其@Async的注解代码如下:
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Async { String value() default ""; }
注解可以使用在类型以及方法中
通过value定义其值,默认是空
一般这个注解需要配合@EnableAsync,起源码如下
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Import({AsyncConfigurationSelector.class}) public @interface EnableAsync { Class<? extends Annotation> annotation() default Annotation.class; boolean proxyTargetClass() default false; AdviceMode mode() default AdviceMode.PROXY; int order() default Integer.MAX_VALUE; }
主要通过该注解放置在启动类中进行配置启动
在启动类中添加如下:
@SpringbootApplication @EnableAsync public class Application{ public static void main(String[] args){ SrpingApplication.run(Application.class, args); } }
2. 用法
2.1 同步调用
从调用到返回函数结果才能执行下一步,称为同步调用
service层 代码:
public class Service{ public void test01() throws InterruptedException{ Thread.sleep(5000); System.out.println("保存日志"); } }
控制层代码模块:
public class Controler{ @Autowired private Service service; @GetMapping("/test") public String getTest(){ try{ System.out.println("开始"); service.test01(); System.out.println("结束"); }catch(InterruptedException e){ e.prinStackTrace(); } } }
通过springboot的启动类启动之后
输出如下:
开始
// 此为等待5秒钟,终端不显示也不关闭
结束
2.2 异步调用
异步调用,执行函数不用等返回结果就可以执行下一步
service层 代码:
主要是添加了@Async注解标识这个方法
public class Service{ @Async public void test01() throws InterruptedException{ Thread.sleep(500); System.out.println("保存日志"); } }
控制层代码模块:
通过调用service层函数
public class Controler{ @Autowired private Service service; @GetMapping("/test") public String getTest(){ try{ System.out.println("开始"); service.test01(); System.out.println("结束"); }catch(InterruptedException e){ e.prinStackTrace(); } } }
以及在启动类中加入注解启动 @EnableAsync
@SpringbootApplication @EnableAsync public class Application{ public static void main(String[] args){ SrpingApplication.run(Application.class, args); } }
3. 自定义线程池
对于线程池的一些基本知识可看我之前的文章:
java如何正确关闭线程以及线程池(代码实践含源码分析)
java线程池的创建方式详细分析(全)
如果不指定线程池,默认使用的线程池为SimpleAsyncTaskExecutor(来一个任务就创建一个线程,不断创建线程导致CPU过高引发OOM),自带的线程池一般都有弊端,一般推荐使用ThreadPoolExecutor(明确线程池的资源,规避风险)
具体如下:
newFixedThreadPool:定死了线程数,任务队列还是无界的,(最大线程数只有队列满了,最大线程数才会创建),所以会造成OOM
newCachedThreadPool:没有设置最大线程数上限,创建大量的线程容易卡顿或者直接OOM
通过自定义线程池可以调整线程池的配置,更好的资源利用
@Async这个注解查找 AsyncConfigurer接口(实现类为AsyncConfigurerSupport,默认配置和方法都是空),所以可重写接口指定线程池。
通过实现接口AsyncConfigurer
继承AsyncConfigurerSupport
自定义TaskExecutor(替代内置任务执行器)
第三种方法:
在application.xml中定义线程池的一些变量
thread.core.size=16 thread.max.size=16 thread.queue.size=30 thread.prefix=xx-
自定义线程池如下
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.ThreadPoolExecutor; @Configuration public class ThreadPoolConfig { // 线程名称前缀 @Value("${thread.prefix}") private String threadPrefix; // 核心线程数 @Value("${thread.core.size}") private int coreSize; // 最大线程数 @Value("${thread.max.size}") private int maxSize; // 队列长度 @Value("${thread.queue.size}") private int queueSize; // 通过bean注解注入 @Bean("xx") public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); //设置线程池参数信息 taskExecutor.setCorePoolSize(coreSize); taskExecutor.setMaxPoolSize(maxSize); taskExecutor.setQueueCapacity(queueSize); taskExecutor.setThreadNamePrefix(threadPrefix); taskExecutor.setWaitForTasksToCompleteOnShutdown(true); taskExecutor.setAwaitTerminationSeconds(30); //修改拒绝策略为使用当前线程执行 taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //初始化线程池 taskExecutor.initialize(); return taskExecutor; } }
以上是java中@Async异步调用的方法的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

Java 8引入了Stream API,提供了一种强大且表达力丰富的处理数据集合的方式。然而,使用Stream时,一个常见问题是:如何从forEach操作中中断或返回? 传统循环允许提前中断或返回,但Stream的forEach方法并不直接支持这种方式。本文将解释原因,并探讨在Stream处理系统中实现提前终止的替代方法。 延伸阅读: Java Stream API改进 理解Stream forEach forEach方法是一个终端操作,它对Stream中的每个元素执行一个操作。它的设计意图是处

Java是热门编程语言,适合初学者和经验丰富的开发者学习。本教程从基础概念出发,逐步深入讲解高级主题。安装Java开发工具包后,可通过创建简单的“Hello,World!”程序实践编程。理解代码后,使用命令提示符编译并运行程序,控制台上将输出“Hello,World!”。学习Java开启了编程之旅,随着掌握程度加深,可创建更复杂的应用程序。
