Spring异步注解—@Async

本文介绍了如何使用Spring框架实现异步任务处理,包括@Async注解的基本使用、自定义线程池执行器的方法以及如何处理异步方法的返回值和异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

被@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。@Async也可以放在类上,表示整个类的所有方法都是异步的。@Async的唯一参数value的作用是:指定用该执行方法的执行器名称,执行器由我们自己定义的,Executor或者TaskExecutor类型;该参数可为空。

基本用法示例代码:

在需要异步执行的方法加上@Async

@Component
public class SendMessge {

    /**
      * 异步发送消息方法
      */
    @Async
    public void send(int message){
        String currentThreadName = Thread.currentThread().getName();
        System.out.println(currentThreadName + ":" + message);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

然后在应用启动类上加上@EnableAsync

@SpringBootApplication
@EnableAsync
public class TestServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestServerApplication.class, args);
    }
}

测试代码

@RunWith(SpringRunner.class)
@SpringBootTest
public class AsyncTest {
    @Autowired
    private SendMessge sendMessge;

    @Test
    public void sendTest() throws InterruptedException {
        for (int i = 0; i < 5; i++){
            sendMessge.send(i);
            System.out.println("send message: " +i);
        }
        Thread.sleep(1000);
    }
}

测试结果

send message: 0
send message: 1
send message: 2
send message: 3
send message: 4
SimpleAsyncTaskExecutor-2:1
SimpleAsyncTaskExecutor-5:4
SimpleAsyncTaskExecutor-3:2
SimpleAsyncTaskExecutor-1:0
SimpleAsyncTaskExecutor-4:3

我们也可以自定义用于执行方法的执行器,这样我们能够控制线程池大小,当我们有多个异步方法时,就可以控制每个方法的并发数量。

/**
 * 配置SendMessage的异步执行器
 */
@Configuration
@EnableAsync
public class ExecutorConfig {
    @Bean
    public Executor sendAsyncExecutor() {
        //spring的线程池执行器
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(10);
        //线程名前缀
        executor.setThreadNamePrefix("sendMessage-Thread-");
        // 线程池无资源时拒绝新任务的处理策略,CallerRunsPolicy 表示由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

然后在我们异步方法注解加上参数:@Async("sendAsyncExecutor"),这样就可以了。

上面的异步方法没有返回值,也不能处理异常,如果异步方法需要返回值和异常的处理就下面这样

@Component
public class SendMessge {

    /**
      * 异步发送消息方法
      */
    @Async("sendAsyncExecutor")
    public ListenableFuture send(String message) throws InterruptedException {
        String currentThreadName = Thread.currentThread().getName();
        Thread.sleep(500);
        if("error".equals(message)) {
            throw new RuntimeException("出错啦");
        }else{
            System.out.println(currentThreadName + ":" + message);
        }
        return new AsyncResult<>("send success: " + message);
    }
}

测试调用

@RunWith(SpringRunner.class)
@SpringBootTest
public class AsyncTest {
    @Autowired
    private SendMessge sendMessge;

    @Test
    public void sendTest() throws ExecutionException, InterruptedException {
        ListenableFuture result = sendMessge.send("error");
        result.addCallback((Object obj) -> { System.out.println(obj);},
                (Throwable ex) -> { System.out.println(ex);});
        Thread.sleep(1000);
    }
}

测试结果

//正常返回
sendMessage-Thread-1:Hi!
send success: Hi!

//异常返回
java.lang.RuntimeException: 出错啦

转载于:https://my.oschina.net/u/2424727/blog/1865858

### Java `@Async` 注解自定义线程池配置及使用方法 #### 配置自定义线程池 为了使 `@Async` 使用特定的线程池而非 Spring 默认提供者,需先创建并配置一个 `TaskExecutor` Bean。这可以通过在任意 `@Configuration` 类中声明来完成。 ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.Executor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @Configuration public class AsyncConfig { @Bean(name = "myExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(25); executor.initialize(); return executor; } } ``` 上述代码片段展示了如何通过设置核心线程数、最大线程数以及队列容量来自定义线程池属性[^1]。 #### 应用 `@Async` 注解 一旦有了自定义线程池,在目标服务类的方法上应用 `@Async` 注解即可让其异步运行。需要注意的是,这里指定了要使用的线程池名称 `"myExecutor"` 来确保该方法由之前定义的任务执行器处理。 ```java import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class AsyncTest { @Async("myExecutor") public void executeAsync() { System.out.println(Thread.currentThread().getName()); System.out.println("Executing asynchronously"); } } ``` 当调用带有 `@Async` 的方法时,它将在不同的线程上下文中被执行,并不会阻塞主线程直到操作完成。 此外,为了让应用程序识别这些配置,还需启用全局异步支持: ```java import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableAsync public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 这样就完成了整个流程——从配置到实际运用 `@Async` 和自定义线程池的工作方式[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值