iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >java中@Async异步调用的方法
  • 585
分享到

java中@Async异步调用的方法

2023-07-02 17:07:25 585人浏览 泡泡鱼
摘要

本篇内容主要讲解“java中@Async异步调用的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java中@Async异步调用的方法”吧!前言异步调用与同步调用同步调用:顺序执行,通过调用返

本篇内容主要讲解“java中@Async异步调用的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java中@Async异步调用的方法”吧!

    前言

    异步调用与同步调用

    • 同步调用:顺序执行,通过调用返回结果再次执行下一个调用

    • 异步调用:通过调用,无需等待返回结果,执行下一个调用

    1. @Async讲解

    其@Async的注解代码如下:

    @Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @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@EnableAsyncpublic 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@EnableAsyncpublic 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=16thread.max.size=16thread.queue.size=30thread.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;@Configurationpublic 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异步调用的方法”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

    --结束END--

    本文标题: java中@Async异步调用的方法

    本文链接: https://www.lsjlt.com/news/343512.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作