首页 > 其他分享 >Spring异步机制:@Async

Spring异步机制:@Async

时间:2023-11-19 16:23:32浏览次数:46  
标签:异步 Thread poolExecutor Spring 线程 Async public

概述

当一个方法标注@Async注解时,该方法的调用将异步发生;这意味着调用者将在调用后立即返回,方法的实际执行将发生在提交给Spring TaskExecutor的任务中。

示例

示例1

使用@EnableAsync注解启用异步机制

@EnableAsync
@Configuration
public class AsyncConfig {
}

 

@Service
public class AsyncJob {
    @Async
    public void asyncMethodWithVoidReturnType() {
        System.out.println("Execute method asynchronously: start."
                + Thread.currentThread().getName());

        try {
            Thread.sleep(10 * 1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Execute method asynchronously: end."
                + Thread.currentThread().getName());
    }
}

 

@RestController
@RequestMapping("/home")
public class HomeController {

    @Autowired
    private AsyncJob asyncJob;

    @GetMapping("/user-info")
    public String queryUserName() {
        asyncJob.asyncMethodWithVoidReturnType();

        return "test - user";
    }
}

 

运行结果

Postman

 

日志

 

从上述日志中线程的名称可以知道,本示例中异步执行方法所用的线程池为Spring boot默认配置的线程池(TaskExecutionAutoConfiguration)

 

示例2

自定义线程池

@Configuration
public class ThreadPoolConfig {
    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor poolExecutor = new ThreadPoolTaskExecutor();
        // 核心线程数
        poolExecutor.setCorePoolSize(1);
        // 最大线程数
        poolExecutor.setMaxPoolSize(3);
        // 队列大小
        poolExecutor.setQueueCapacity(5);
        // 线程最大空闲时间
        poolExecutor.setKeepAliveSeconds(60);
        // 拒绝策略
        poolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        // 线程名称前缀
        poolExecutor.setThreadNamePrefix("sendMessage-");

        return poolExecutor;
    }
}

 

@Service
public class AsyncJob {
    @Async("taskExecutor")
    public void asyncMethodWithVoidReturnType() {
        System.out.println("Execute method asynchronously: start."
                + Thread.currentThread().getName());

        try {
            Thread.sleep(10 * 1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Execute method asynchronously: end."
                + Thread.currentThread().getName());
    }
}

 

public class AsyncJobTest extends BaseTest {
    @Autowired
    private AsyncJob asyncJob;

    @Test
    void check_async() {
        System.out.println("check_async. "
                + Thread.currentThread().getName());

        asyncJob.asyncMethodWithVoidReturnType();

        try {
            Thread.sleep(30 * 1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

运行结果

 

特别说明

如果项目中配置了多个线程池,在@Async注解中必须指明具体的线程池,否则会有如下类似报错

(1)多个线程池,且其中某个线程池的名称为taskExecutor

 

本质原因:ThreadPoolTaskScheduler、ThreadPoolTaskExecutor都是org.springframework.core.task.TaskExecutor的子类

 

(2)多个线程池,且任何线程池的名称均不为taskExecutor

 

此时将使用默认构建的线程池(即SimpleAsyncTaskExecutor的实例)异步执行方法

具体细节见下一章

 

揭秘 - 线程池

(1)通过@Async注解指定线程池的秘密

 

 

 

(2)使用Spring boot默认线程池(即:taskExecutor) 或者 SimpleAsyncTaskExecutor 的秘密

 

 

 

Future

如果@Async方法需要返回运行结果,可声明方法返回值为Future类型:

A、可以声明为常规的Java .util.concurrent. future类型

B、可以声明为Spring的org.springframework.util.concurrent.ListenableFuture类型

C、从Spring 4.2开始也可以声明为Java中的CompletableFuture

@Service
public class AsyncJob {

  @Async
  public CompletableFuture<Integer> getEmployeeCount() {
    int count = 0;
    // ...
    return CompletableFuture.completedFuture(count);
  }
}

 

扩展阅读

How To Do @Async in Spring | Baeldung

 

标签:异步,Thread,poolExecutor,Spring,线程,Async,public
From: https://www.cnblogs.com/studyLog-share/p/14988363.html

相关文章

  • SpringCloud应用集成Nacos服务注册与发现
    SpringCloud应用集成Nacos服务注册与发现官方文档第一步:引入依赖版本见=>附录:根pom文件=>版本控制片段www.cnblogs.com/anhaoyan... <!--引入nacos用于服务注册与发现--><dependency><groupId>com.alibaba.cloud</groupId><artifact......
  • SpringCloud应用集成Nacos和Dubbo
    SpringCloud应用集成Nacos和Dubbo官网教程官方demo第一步:引入依赖版本见=>附录:根pom文件=>版本控制片段www.cnblogs.com/anhaoyan... <!--SpringBoot依赖--><dependency><groupId>org.springframework.boot</groupId><artifa......
  • SpringCloudAlibaba
    SpringCloudAlibaba官网地址什么是SpringCloudAlibabaSpringCloudAlibaba致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用服务的必需组件,方便开发者通过SpringCloud编程模型轻松使用这些组件来开发分布式应用服务。依托SpringCloudAlibaba,您只需要......
  • SpringCloudAlibaba版本关系
    SpringCloudAlibaba版本关系官方云原生应用脚手架由于SpringBoot3.0,SpringBoot2.7~2.4和2.4以下版本之间变化较大,目前企业级客户老项目相关SpringBoot版本仍停留在SpringBoot2.4以下,为了同时满足存量用户和新用户不同需求,社区以SpringBoot3.0和2.4分别为......
  • SpringCloud应用集成Nacos配置中心
    SpringCloud应用集成Nacos配置中心官方文档第一步:引入依赖版本见=>附录:根pom文件=>版本控制片段www.cnblogs.com/anhaoyan...<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-con......
  • Spring拦截器(Interceptor)的使用
    一.注册拦截器,定义一个类实现HandlerInterceptor接口,重写里面的三个方法,具体代码实现如下:packagecom.luoluo.interceptor;importorg.springframework.stereotype.Component;importorg.springframework.web.servlet.HandlerInterceptor;importorg.springframework.web.se......
  • SpringCloud应用集成Nacos服务注册与发现
    SpringCloud应用集成Nacos服务注册与发现官方文档第一步:引入依赖版本见=>附录:根pom文件=>版本控制片段www.cnblogs.com/anhaoyan... <!--引入nacos用于服务注册与发现--><dependency><groupId>com.alibaba.cloud</groupId><artifact......
  • SpringCloud应用集成Nacos和Dubbo
    SpringCloud应用集成Nacos和Dubbo官网教程官方demo第一步:引入依赖版本见=>附录:根pom文件=>版本控制片段www.cnblogs.com/anhaoyan... <!--SpringBoot依赖--><dependency><groupId>org.springframework.boot</groupId><artifa......
  • Spring Boot 如何获取Excel sheet页的数量?
    前言在日常的开发中,我们经常需要读取Excel文件中的数据,其中涉及到获取Excel中sheet页的数量。本文将介绍如何使用SpringBoot获取Excelsheet页的数量。摘要本文主要介绍了如何使用SpringBoot获取Excel文件中sheet页的数量。首先通过POI库读取Excel文件,然后通过Workbook对象获......
  • 使用Swagger,在编写配置类时报错Caused by: java.lang.NullPointerException: Cannot i
    1.问题Causedby:java.lang.NullPointerException:Cannotinvoke"org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()"because"this.condition"isnull2.解决参考链接:解决Cannotinvoke"org.springframework......