일이 끝나기를 기다리지 않고, 다음 작업을 하는 것을 말합니다.
ex) A와 B가 은행 업무 처리를 위해 은행에 A -> B 순서로 도착했을 때.
Spring에서 비동기 처리를 가능하게 해주는 @Async 어노테이션!
AsyncApplication.class
@SpringBootApplication
@EnableAsync
public class AsyncApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncApplication.class, args);
}
}
AsyncAService.class
@Service
public class AsyncAService {
@Async
public void testA(){
System.out.println("A");
}
@Async
public void testB() throws InterruptedException {
Thread.sleep(3000);
System.out.println("B");
}
}
AsyncController.class
@RestController
@RequiredArgsConstructor
public class AsyncController {
private final AsyncAService asyncAService;
@GetMapping("")
public void testAsync() throws InterruptedException {
asyncAService.testB();
asyncAService.testA();
}
}
B가 먼저 실행됐음에도 A가 먼저 출력되는 것을 확인할 수 있습니다.
자가호출을 하면 안된다.
같은 클래스에서 호출을 하면 안 된다!
AsyncAService.class
@Service
public class AsyncAService {
@Async
public void testA(){
System.out.println("A");
}
@Async
public void testB() throws InterruptedException {
Thread.sleep(3000);
System.out.println("B");
}
public void testC() throws InterruptedException {
testB();
testA();
}
}
AsyncController.class
@RestController
@RequiredArgsConstructor
public class AsyncController {
private final AsyncAService asyncAService;
@GetMapping("")
public void testAsync() throws InterruptedException {
asyncAService.testC();
}
}
위와 같이 AsyncAService에서 testA()와 testB()를 호출하는 testC()를 만듭니다.
AsyncController에서 AsyncAService의 testC()를 호출합니다.
@Async 어노테이션을 붙였음에도 비동기로 처리가 되지 않고, testB()가 먼저 실행되고, 완료 후에 testA()가 실행됩니다.
AsyncAService.class
@Service
@RequiredArgsConstructor
public class AsyncAService {
private final AsyncBService asyncBService;
@Async
public void testA(){
System.out.println("A");
}
public void testC() throws InterruptedException {
asyncBService.testB();
testA();
}
}
AsyncBService.class
@Service
public class AsyncBService {
@Async
public void testB() throws InterruptedException {
Thread.sleep(3000);
System.out.println("B");
}
}
AsyncController.class
@RestController
@RequiredArgsConstructor
public class AsyncController {
private final AsyncAService asyncAService;
@GetMapping("")
public void testAsync() throws InterruptedException {
asyncAService.testC();
}
}
AsyncAService.class
@Service
public class AsyncAService {
@Async
public void testA(){
System.out.println("A");
}
}
AsyncBService.class
@Service
@RequiredArgsConstructor
public class AsyncBService {
private final AsyncAService asyncAService;
@Async
public void testB() throws InterruptedException {
Thread.sleep(3000);
System.out.println("B");
}
public void testC() throws InterruptedException {
asyncBService.testB();
testA();
}
}
AsyncController.class
@RestController
@RequiredArgsConstructor
public class AsyncController {
private final AsyncBService asyncBService;
@GetMapping("")
public void testAsync() throws InterruptedException {
asyncBService.testC();
}
}
AsyncAService.class
@Service
public class AsyncAService {
@Async
public void testA(){
System.out.println("A");
}
@Async
public void testB() throws InterruptedException {
Thread.sleep(3000);
System.out.println("B");
}
}
AsyncBService.class
@Service
@RequiredArgsConstructor
public class AsyncBService {
private final AsyncAService asyncAService;
public void testC() throws InterruptedException {
asyncAService.testB();
asyncAService.testA();
}
}
AsyncController.class
@RestController
@RequiredArgsConstructor
public class AsyncController {
private final AsyncBService asyncBService;
@GetMapping("")
public void testAsync() throws InterruptedException {
asyncBService.testC();
}
}
AsyncController.class
@RestController
@RequiredArgsConstructor
public class AsyncController {
private final AsyncBService asyncBService;
@GetMapping("")
public void testAsync() throws InterruptedException {
asyncBService.testC();
}
}
@Async를 Thread pool로 커스텀할 수 있습니다!
AsyncApplication.class
@SpringBootApplication
public class AsyncApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncApplication.class, args);
}
}
AsyncConfig.class
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean(name = "asyncThreadPoolExecutor")
public Executor asyncThreadPoolExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(3);
taskExecutor.setMaxPoolSize(30);
taskExecutor.setQueueCapacity(100);
taskExecutor.setThreadNamePrefix("Executor-");
return taskExecutor;
}
}
AsyncAService
@Service
public class AsyncAService {
@Async("asyncThreadPoolExecutor")
public void testA(){
System.out.println("A");
}
@Async("asyncThreadPoolExecutor")
public void testB() throws InterruptedException {
Thread.sleep(3000);
System.out.println("B");
}
}