惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
A
About on SuperTechFans
Microsoft Azure Blog
Microsoft Azure Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tailwind CSS Blog
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
Y
Y Combinator Blog
博客园 - 三生石上(FineUI控件)
大猫的无限游戏
大猫的无限游戏
Help Net Security
Help Net Security
Security Latest
Security Latest
Recorded Future
Recorded Future
S
Secure Thoughts
P
Privacy International News Feed
L
Lohrmann on Cybersecurity
Vercel News
Vercel News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Google DeepMind News
Google DeepMind News
L
LINUX DO - 热门话题
T
The Blog of Author Tim Ferriss
T
Threatpost
宝玉的分享
宝玉的分享
PCI Perspectives
PCI Perspectives
V
Vulnerabilities – Threatpost
WordPress大学
WordPress大学
C
CERT Recently Published Vulnerability Notes
GbyAI
GbyAI
S
Schneier on Security
S
Security @ Cisco Blogs
S
Securelist
SecWiki News
SecWiki News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Jina AI
Jina AI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
H
Heimdal Security Blog
D
DataBreaches.Net
M
MIT News - Artificial intelligence
Microsoft Security Blog
Microsoft Security Blog
A
Arctic Wolf
C
Cybersecurity and Infrastructure Security Agency CISA
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Schneier on Security
Schneier on Security
C
Check Point Blog
D
Docker

博客园 - 时空穿越者

java并发:深入解析 ThreadPoolExecutor.addWorker() 流水线技术解析:处理器重排序的硬件基础 java并发:synchronized 揭秘 java并发:管道流(Piped Streams)的应用场景 java并发:再次认识一下Java中的锁 —— 类级别的锁是否存在? LangGraph:add_conditional_edges详解 Spring BeanDefinition Spring Resource Spring之ApplicationContext Spring之BeanFactory:解析getBean()方法 Spring之IoC容器 Spring的整体架构 Spring Data JPA:解析CriteriaQuery Spring Data JPA:解析CriteriaBuilder Spring Data JPA:解析JpaSpecificationExecutor & Specification Spring Data JPA:解析SimpleJpaRepository java并发:线程池之Executors(ScheduledExecutorService篇) java并发:线程池之饱和策略 java并发:线程池之ThreadPoolExecutor
Spring异步机制:@Async
时空穿越者 · 2023-11-19 · via 博客园 - 时空穿越者

在 Spring 框架中,线程池的抽象主要通过 TaskExecutor 接口实现(对标 JDK 的 Executor),并结合 Async 注解简化异步任务。

概述

当一个方法标注@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();
        }
    }
}

运行结果

揭秘 - 线程池

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

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

补充 - Spring Boot默认提供了名称为taskExecutor的线程池,所以我们在程序中不应该再自定义名称为taskExecutor的线程池

此处示例是通过@Autowire注解的方式注入线程池,区别于前面异步注解中指明线程池的方式

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