Spring异步机制:@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

 
posted @ 2023-11-19 16:09  时空穿越者  阅读(88)  评论(0编辑  收藏  举报