본문 바로가기

Spring/공부공부

[Spring] @Async 비동기 처리 ( SimpleAsyncTaskExecutor )

 

@Async

메서드를 비동기적으로 실행하기 위해 사용하는 어노테이션.

별도의 스레드 풀에서 실행되며, 메서드의 호출과 실행이 분리된다. 

호출자는 메서드가 끝날때까지 기다리지 않고 바로 제어를 반환, 메서드 내부 실행은 백그라운드 스레드에서 처리.

 

@Async   => 기본 스레드 풀 사용.

@Async("taskExecutor")  => 명시한 스레드 풀 사용.

@Service
public class MyService {

    @Async("taskExecutor")  // taskExecutor 사용
    public void customAsyncMethod() {
        System.out.println("Executing with customTaskExecutor");
    }
}

 


 

@EnableAsync

스프링 애플리케이션에서 비동기 작업을 활성화하기 위해 사용하는 어노테이션.

설정 클래스에 추가해야 @Async이 적용된 메서드가 제대로 동작 할 수 있음. (비동기 처리 기능을 전역적으로 활성화)

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;

@Configuration
@EnableAsync
public class AsyncConfig {
    // 비동기 설정이 필요한 경우 추가 가능
}

 

기본 설정 : SimpleAsyncTaskExecutor => 스레드 풀을 사용하지 않고, 요청마다 새로운 스레드를 생성.

커스텀 설정 : ThreadPoolTaskExecutor => 스레드 풀 패턴을 사용. 스레드 풀의 갯수 크기 등 세밀한 조정 가능.

 

(커스텀 스레드 풀 설정)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean(name = "taskExecutor", destroyMethod = "shutdown")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);      // 기본 스레드 수
        executor.setMaxPoolSize(10);      // 최대 스레드 수
        executor.setQueueCapacity(100);   // 큐 사이즈
        executor.setThreadNamePrefix("AsyncThread-");  // 스레드 이름 접두사
        executor.initialize();
        return executor;
    }
}

 

 - setCorePoolSize (int corePoolSize) : 스레드 풀의 기본 크기 설정. (기본적으로 유지되는 스레드의 수)

  스레드 풀에 작업이 들어오지 않더라도 지정한 만큼의 스레드가 항상 대기 상태로 유지.

 

 - setMaxPoolSize (int maxPoolSize) : 스레드 풀에서 사용할 수 있는 최대 스레드 수 설정. (동시 사용 가능한 최대 수)

  작업이 corePoolSize보다 많아지면, 최대 maxPoolSize까지 스레드가 증가하여 추가 작업 처리.

 

 - setQueueCapacity (int queueCapacity) : 스레드가 부족할 때, 작업을 대기시킬 큐의 크기 설정.

  스레드가 실행중이어서 바로 실행할 수 없는 작업이 있다면, 지정한 갯수의 작업까지 대기 상태로 보관.

* 큐(queue) : 동시에 실행할 수 있는 스레드의 수가 초과되었을 때, 대기중인 작업을 담아 두는 공간.

 

- setThreadNamePrefix (String namePrefix) : 생성되는 스레드의 이름에 붙일 접두사를 설정.

 디버깅이나 모니터링 시 어떤 작업이 어떤 스레드에서 실행되는지 쉽게 파악 가능.

  * executor.setThreadNamePrefix("AsyncThread-")  =>  "AsyncThread-1", "AsyncThread-2" 

 

- initialize() : 설정이 완료된 스레드 풀을 초기화.

  ThreadPoolTaskExecutor 설정이 완료된 후, 스레드 풀을 사용할 준비가 되었다는 것을 나타내는 메서드.

  이 메서드를 호출해야 스레드 풀 설정이 적용되고 스레드 풀을 실행할 수 있는 상태로 만들 수 있음.

 


 

 - setKeepAliveSeconds (int seconds) : 스레드가 풀에 반환되기 전에(유휴 상태 스레드가) 유지되는 시간을 설정.

 

 - setAllowCoreThreadTimeOut (boolean allow) : corePoolSize에 해당하는 스레드도 타임아웃이 가능하도록 설정.

 

 - setRejectedExecutionHandler (RejectedExecutionHandler handler) : 작업이 거부되었을 때 어떻게 처리할 지 설정.

     - AbortPolicy : 기본 처리 방식. 작업이 거부되면 예외 던짐.

     - CallerRunsPolicy : 호출한 스레드에서 직접 작업을 수행.

     - DiscardPolicy : 거부된 작업을 무시.

     - DiscardOldestPolicy : 가장 오래된 대기 작업을 제거하고, 새로운 작업을 큐에 추가.

     * executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

 

 - setThreadPriority (int priority) : 생성되는 스레드의 우선순위 설정.

  Thread.MIN_PRIORITY  ~  Thread.NORM_PRIORITY  ~  Thread.MAX_PRIORITY

 

 - setWaitForTasksToCompleteOnShutdown (boolean wait) :

    스레드 풀 종료 시, 진행 중인 작업이 완료될 때까지 대기할 지 설정.

 - setAwaitTerminationSeconds (int seconds) : 스레드 풀 종료 시 대기 시간 설정.

  스레드 풀이 종료될 때, 진행 중인 작업이 얼마나 오래 대기할지 설정. 지정 시간 초과 시 스레드 풀 강제 종료.

executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);

=> 함께 사용. (스레드 풀을 종료할 때 최대 60초 동안 대기하고, 이 시간이 지나면 강제로 스레드를 종료)

 

 - shutdown() : 스레드 풀을 종료하는 메서드 ( 생략가능, 기본값이 destroyMethod에 설정됨)

스레드 풀을 종료하고, 더 이상 새로운 작업이 제출되지 않도록 막음. 대기/진행 중인 작업은 안전하게 처리.