异步调用

异步调用同步调用,即:程序按定义的顺序依次执行的过程,每一行代码执行过程必须等待上一行代码执行完毕后才执行。而异步调用指:程序在执行时,无需等待执行的返回值可继续执行后面的代码。回调。其主要是解决异步方法执行

大家好,又见面了,我是你们的朋友全栈君。

       同步调用,即:程序按定义的顺序依次执行的过程,每一行代码执行过程必须等待上一行代码执行完毕后才执行。而异步调用指:程序在执行时,无需等待执行的返回值可继续执行后面的代码。回调。其主要是解决异步方法执行结果的处理方法,比如在希望异步调用结束时返回执行结果,这个时候就可以考虑使用回调机制。

  需要在启动类加入@EnableAsync使异步调用@Async注解生效

@Component
public class SyncService {
    
    @Async
    public void asyncEvent() throws InterruptedException {
        //休眠1s
        Thread.sleep(1000);
        //log.info("异步方法输出:{}!", System.currentTimeMillis());
    }

}

  在默认情况下,未设置TaskExecutor时,默认是使用SimpleAsyncTaskExecutor这个线程池,但此线程不是真正意义上的线程池,因为线程不重用,每次调用都会创建一个新的线程。可通过控制台日志输出可以看出,每次输出线程名都是递增的。

  调用的异步方法,不能为同一个类的方法,因为Spring在启动扫描时会为其创建一个代理类,而同类调用时,还是调用本身的代理类的,所以和平常调用是一样的。其他的注解如@Cache等也是一样的道理,就是Spring的代理机制造成的。

  创建一个自定义的ThreadPoolTaskExecutor线程池:

@Configuration
public class Config {

    /**
     * 配置线程池
     * @return
     */
    @Bean(name = "asyncPoolTaskExecutor")
    public ThreadPoolTaskExecutor getAsyncThreadPoolTaskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(20);
        taskExecutor.setMaxPoolSize(200);
        taskExecutor.setQueueCapacity(25);
        taskExecutor.setKeepAliveSeconds(200);
        taskExecutor.setThreadNamePrefix("King-");
        // 线程池对拒绝任务(无线程可用)的处理策略,目前只支持AbortPolicy、CallerRunsPolicy;默认为后者
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //调度器shutdown被调用时等待当前被调度的任务完成
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        //等待时长
        taskExecutor.setAwaitTerminationSeconds(60);
        taskExecutor.initialize();
return taskExecutor; } }

  若需要在关闭线程池时等待当前调度任务完成后才开始关闭,可以通过简单的配置,进行优雅的停机策略配置。关键就是通过setWaitForTasksToCompleteOnShutdown(true)setAwaitTerminationSeconds方法。

  • setWaitForTasksToCompleteOnShutdown:表明等待所有线程执行完,默认为false
  • setAwaitTerminationSeconds:等待的时间,因为不能无限的等待下去。

      使用的是就只需要在@Async加入线程池名称即可:

@Async("asyncPoolTaskExecutor")
    public void asyncEvent() throws InterruptedException {
        //休眠1s
        Thread.sleep(1000);
        log.info("异步方法内部线程名称:{}!", Thread.currentThread().getName());
    }

  异步回调及超时处理

  需要异步回调的返回值时,就需要使用异步回调来完成了。主要就是通过Future进行异步回调。

@Async("asyncPoolTaskExecutor")
public Future<String> asyncEvent() throws InterruptedException {
    //休眠1s
    Thread.sleep(1000);
    log.info("异步方法内部线程名称:{}!", Thread.currentThread().getName());
    return new AsyncResult<>("异步方法返回值");
}

  AsyncResultSpring提供的一个Future接口的子类。然后通过isDone方法,判断是否已经执行完毕。

  超时处理

  对于Future配置超时,很简单,通过get方法即可,具体如下: 

//get方法会一直堵塞,直到等待执行完成才返回
//get(long timeout, TimeUnit unit) 在设置时间类未返回结果,会直接排除异常TimeoutException,messages为null
String result = doFutrue.get(60, TimeUnit.SECONDS);//60s

  超时后,会抛出异常TimeoutException类,此时可进行统一异常捕获即可

注意:

  @Async所修饰的函数不要定义为static类型,这样异步调用不会生效,

  @Async调用中的事务处理机制

  在@Async标注的方法,同时也适用了@Transactional进行了标注;在其调用数据库操作之时,将无法产生事务管理的控制,原因就在于其是基于异步处理的操作。那该如何给这些操作添加事务管理呢?可以将需要事务管理操作的方法放置到异步方法内部,在内部被调用的方法上添加@Transactional.
  例如: 方法A,使用了@Async/@Transactional来标注,但是无法产生事务控制的目的。方法B,使用了@Async来标注, B中调用了C、D,C/D分别使用@Transactional做了标注,则可实现事务控制的目的。
  基于@Async调用中的异常处理机制
  在异步方法中,如果出现异常,对于调用者caller而言,是无法感知的。

  

   

       

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/154204.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • GO Excel 转 JSON (完整代码)[通俗易懂]

    GO Excel 转 JSON (完整代码)[通俗易懂]packagemainimport( “fmt” “github.com/xuri/excelize/v2” “io/ioutil” “os” “path/filepath”)funcinit(){}//配置文件目录varconfigPathstring=”../../Configs”varoutjsonPathstring=”./json/”funcgetFileList(pathstring)[]string{ varall_f.

    2022年5月8日
    50
  • webservice安全策略[通俗易懂]

    webservice安全策略[通俗易懂]前些日子公司的应用要和合作方对接,我参与了webservice这块的工作,在访问量很小的情况下基本上完成了功能,但安全这块没有找到合适的方案,所以自己做了些旁门左道的设想,不一定合理和完善,希望能起个

    2022年7月2日
    33
  • SpringSecurity权限管理系统实战—一、项目简介和开发环境准备

    SpringSecurity权限管理系统实战—一、项目简介和开发环境准备SpringSecurity实战一—项目简介和开发环境准备一、简介​ 在企业应用中,认证和授权是非常重要的一部分内容,业界最出名的两个框架就是大名鼎鼎的Shiro和SpringSecurity。本次我选取的是和SpringBoot更好兼容的SpringSecurity。

    2025年6月7日
    3
  • 正版哈希值校验工具_哈希校验

    正版哈希值校验工具_哈希校验macos和windows平台的哈希校验

    2025年11月6日
    5
  • .Net培训班课程体系

    .Net培训班课程体系.Net培训第一部分:.Net基础

    2022年7月1日
    28
  • 详解MIPI协议

    详解MIPI协议目录前言MIPI简介MIPI联盟的MIPIDSI规范MIPI名词解释MIPIDSI分层结构command和video模式D-PHYLane模组Lane全局架构Lane电压和状态DATALANE操作模式时钟LANE低功耗状态高速数据传输高速CLK传输D-PHY总结DSICSI前言MIPI接口的内部非常复杂,如果不是专门去做MIPI接口,没有必要像研究H264一样往深入的去研究。我们知道MIPI协议连接了camera与soc、LCD和soc,作为此间的开发者,我们只需要关注他怎么使用就可以了知识

    2022年4月28日
    212

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号