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

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 时空穿越者

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