Spring Boot에 Java 21 LTS 가상 스레드 및 Async 및 Scheduled 어노테이션 사용 하기
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.5'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.example.vt'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '21'
}
configurations {
all {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/release/' }
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-log4j2'
implementation 'mysql:mysql-connector-java:8.0.33'
compileOnly 'org.projectlombok:lombok:1.18.32'
annotationProcessor 'org.projectlombok:lombok:1.18.32'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
}
tasks.named('jar') {
enabled = false
}
tasks.named('test') {
useJUnitPlatform()
}
application.yml
server:
shutdown: graceful
spring:
threads:
virtual:
enabled: true
task:
execution:
thread-name-prefix: vt-task-
pool:
core-size: 1
scheduling:
thread-name-prefix: vt-scheduling-
ExecutorServiceConfig.java
package com.example.vt.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading;
import org.springframework.boot.autoconfigure.thread.Threading;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Configuration
public class ExecutorServiceConfig {
@Bean
@ConditionalOnThreading(Threading.VIRTUAL)
public ExecutorService virtualThreadExecutor() {
return Executors.newVirtualThreadPerTaskExecutor();
}
}
AsyncConfig.java
package com.example.vt.config;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.support.TaskExecutorAdapter;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Bean(name = "virtualAsyncTaskExecutor")
public AsyncTaskExecutor virtualAsyncTaskExecutor(@Qualifier("virtualThreadExecutor") ExecutorService virtualThreadExecutor) {
return new TaskExecutorAdapter(virtualThreadExecutor);
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
public static class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... params) {
//log("Exception Name - {}", throwable.getClass().getName());
//log("Exception message - {}", throwable.getMessage());
//log("Method name - {}", method.getName());
for (Object param : params) {
//log("Parameter value - {}", param);
}
}
}
}
ApiScheduler.java
package com.example.vt;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import lombok.extern.log4j.Log4j2;
import java.util.concurrent.TimeUnit;
@Log4j2
@RequiredArgsConstructor
@Component
public class ApiScheduler {
@Scheduled(initialDelay = 3L, fixedDelay = 3L, timeUnit = TimeUnit.SECONDS)
public void scheduleFixedDelay() {
log.info("scheduleFixedDelay");
}
@Scheduled(cron = "*/3 * * * * ?", zone = "UTC")
public void scheduleCron() {
log.info("scheduleCron");
}
}
PushService.java
package com.example.vt.service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class PushService {
@Async("virtualAsyncTaskExecutor")
public void push() {
//log("push");
}
}
Application.java
package com.example.vt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
스프링 부트에서 가상 스레드를 사용하기 위해 설정 파일에서 활성화 application.yml
spring:
threads:
virtual:
enabled: true
간략한 스프링 부트 설정과 어노테이션 추가로 스케쥴러와 비동기 작업
@EnableScheduling, @Scheduled 어노테이션 추가로 스프링 부트에서 스케쥴러를 사용
@EnableAsync, @Async 어노테이션 추가로 스프링 부트에서 해당 메서드를 비동기 작업
플랫폼 스레드 보다 가상 스레드 사용으로 처리량을 높일 수 있다.
references
https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html
https://docs.spring.io/spring-framework/reference/integration/scheduling.html
'spring' 카테고리의 다른 글
spring boot custom auto configuration (0) | 2024.10.12 |
---|---|
spring boot fast log4j2 (0) | 2024.10.12 |
spring boot 가상 스레드 (0) | 2024.10.12 |
spring boot 가상 스레드로 Redis 사용 (0) | 2024.10.12 |
spring boot 가상 스레드로 웹소켓 사용 (0) | 2024.10.08 |