자바에서 비동기를 사용하려면 쓰레드를 이용을 하였습니다
static ExecutorService executorService = Executors.newFixedThreadPool(5);
public void asyncMethod(final String message) throws Exception {
executorService.submit(new Runnable() {
@Override
public void run() {
// do something
}
});
}
Excutors를 사용해 ThreadPool 생성을 하고
비동기로 작동할 기능을 등록시켜 작동하면 됐습니다.
submit 말고 다양하게 실행시킬 수 있습니다.
코틀린의 코루틴 이나 자바스크립트의 async, await
비동기를 동기적으로 작성할 수 있다는것이 너무나도 부러웠습니다.
그래서 이것저것 찾아보다가
@Async
을 발견했습니다.
@EnableAsync
@SpringBootApplication
public class SpringBootApplication {
}
Async 어노테이션을 사용하려면 Application Class에
@EnableAsync
를 적용시켜야 합니다.
@Async
public void asyncMethod(int i) {
try {
Thread.sleep(500);
System.out.println(i + "번째 작동");
} catch(InterruptedException e) {
e.printStackTrace();
}
}
비동기로 작동하고 싶은 메소드에 @Async
를 붙여주시면 됩니다.
@Async
의 기본 설정은 SimpleAsyncTaskExecutor
를 사용하게 됩니다.
만약 원하는 설정을 하고싶으면 AsyncConfigurerSupport
를 상속받아서 원하는대로 설정하시면 될것같습니다.
@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // Poolsize
executor.setMaxPoolSize(30); // max Pool
executor.setQueueCapacity(50); // queue 용량
executor.setThreadNamePrefix("DDAJA-ASYNC-");
executor.initialize();
return executor;
}
}
이렇게 Async 환경설정을 해주면 똑같이 @Async
를 적용만 시켜주면 해당 환경들이 적용이 됩니다.
private method는 사용 불가, public method만 사용 가능
self-invocation(자가 호출) 불가, 즉 inner method는 사용 불가
QueueCapacity 초과 요청에 대한 비동기 method 호출시 방어 코드 작성
그 이유는
@Async
의 동작은 AOP가 적용되어 Spring Context에서 등록된 Bean Object의 method가 호출 될 시에,
Spring이 확인할 수 있고 @Async
가 적용된 method의 경우 Spring이 method를 가로채 다른 Thread에서 실행 시켜주는 동작 방식입니다.
이 때문에 Spring이 해당 @Async method를 가로챈 후, 다른 Class에서 호출이 가능해야 하므로,private method는 사용할 수 없습니다.
@Controller
public class TestController {
@Async
public void asyncMethod(int i) {
try {
Thread.sleep(500);
System.out.println(i + "번째 작동");
} catch(InterruptedException e) {
e.printStackTrace();
}
}
@GetMapping("async")
public String testAsync() {
for(int i = 0; i < 50; i++) {
asyncMethod(i);
}
return "";
}
}
자기 호출로 비동기를 한번 테스트 해보았습니다.
비동기가 아닌 동기적으로 작동된것을 보아 @Async
이 적용이 안된것을 확인할 수 있었습니다.
@Service
public class TestService {
@Async
public void asyncMethod(int i) {
try {
Thread.sleep(500);
System.out.println(i + "번째 작동");
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
@Controller
public class TestController {
@Autowired // 귀찮아서 Autowired 씀
private TestService testService;
@GetMapping("async")
public String testAsync() {
for(int i = 0; i < 50; i++) {
testService.asyncMethod(i);
}
return "";
}
}
비동기로 작동되는 모습을 제대로 확인하였습니다.
@Async
어노테이션으로 비동기를 좀더 쉽게 작성할 수 있어서 좋았지만
이것 역시 Custom 해서 써야할것같고
당연한 이야기겠지만 Thread를 결국 관리를 해줘야된다는 점에서
Thread를 리스크를 지니게 되는것같습니다.
(저는 Thread 관리가 가장 무서워요 ㅠㅠ)
Java에서 코틀린의 코루틴 또는 자바스크립트의 async await 과 같은 기능이
지원됐으면 좋겠습니다.........