前言
异步调用与同步调用
同步调用:顺序执行,通过调用返回结果再次执行下一个调用
异步调用:通过调用,无需等待返回结果,执行下一个调用
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中文网其他相关文章!

本文讨论了使用Maven和Gradle进行Java项目管理,构建自动化和依赖性解决方案,以比较其方法和优化策略。

本文使用Maven和Gradle之类的工具讨论了具有适当的版本控制和依赖关系管理的自定义Java库(JAR文件)的创建和使用。

本文讨论了使用咖啡因和Guava缓存在Java中实施多层缓存以提高应用程序性能。它涵盖设置,集成和绩效优势,以及配置和驱逐政策管理最佳PRA

本文讨论了使用JPA进行对象相关映射,并具有高级功能,例如缓存和懒惰加载。它涵盖了设置,实体映射和优化性能的最佳实践,同时突出潜在的陷阱。[159个字符]

Java的类上载涉及使用带有引导,扩展程序和应用程序类负载器的分层系统加载,链接和初始化类。父代授权模型确保首先加载核心类别,从而影响自定义类LOA


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

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

热门文章

热工具

Dreamweaver Mac版
视觉化网页开发工具

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

SublimeText3 Linux新版
SublimeText3 Linux最新版

WebStorm Mac版
好用的JavaScript开发工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。