docs
Package: org.springframework.boot.thread
The thread package provides classes for configuring and managing threading models in Spring Boot applications, with support for both platform and virtual threads.
Enum representing the threading model of the application.
public enum Threading {
PLATFORM {
@Override
public boolean isActive(Environment environment);
},
VIRTUAL {
@Override
public boolean isActive(Environment environment);
};
public abstract boolean isActive(Environment environment);
}Threading Modes:
PLATFORM - Traditional platform threads (default)
VIRTUAL - Lightweight virtual threads (Project Loom)
spring.threads.virtual.enabled=true AND running Java 21+@Component
public class ThreadingChecker {
private final Environment environment;
public ThreadingChecker(Environment environment) {
this.environment = environment;
}
public void checkThreadingMode() {
if (Threading.VIRTUAL.isActive(environment)) {
System.out.println("Using virtual threads");
} else if (Threading.PLATFORM.isActive(environment)) {
System.out.println("Using platform threads");
}
}
}# application.properties
spring.threads.virtual.enabled=true# application.yml
spring:
threads:
virtual:
enabled: true@Configuration
public class ThreadingConfiguration {
@Bean
@ConditionalOnExpression("${spring.threads.virtual.enabled:false} && T(org.springframework.boot.system.JavaVersion).getJavaVersion().isEqualOrNewerThan(T(org.springframework.boot.system.JavaVersion).TWENTY_ONE)")
public ThreadPoolTaskExecutor virtualThreadTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setThreadFactory(Thread.ofVirtual().factory());
executor.initialize();
return executor;
}
@Bean
@ConditionalOnExpression("!${spring.threads.virtual.enabled:false} || !T(org.springframework.boot.system.JavaVersion).getJavaVersion().isEqualOrNewerThan(T(org.springframework.boot.system.JavaVersion).TWENTY_ONE)")
public ThreadPoolTaskExecutor platformThreadTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(100);
executor.initialize();
return executor;
}
}@Service
public class AsyncService {
private final Environment environment;
private final Logger logger = LoggerFactory.getLogger(AsyncService.class);
public AsyncService(Environment environment) {
this.environment = environment;
logThreadingMode();
}
private void logThreadingMode() {
String mode = Threading.VIRTUAL.isActive(environment)
? "virtual threads"
: "platform threads";
logger.info("Application is using {}", mode);
}
@Async
public CompletableFuture<String> processAsync() {
String threadType = Thread.currentThread().isVirtual()
? "virtual"
: "platform";
logger.info("Processing on {} thread: {}",
threadType, Thread.currentThread().getName());
return CompletableFuture.completedFuture("Result");
}
}@Component
public class ThreadingAwareComponent {
private final boolean useVirtualThreads;
public ThreadingAwareComponent(Environment environment) {
this.useVirtualThreads = Threading.VIRTUAL.isActive(environment);
}
public ExecutorService createExecutorService() {
if (useVirtualThreads) {
// Use virtual threads
return Executors.newVirtualThreadPerTaskExecutor();
} else {
// Use platform threads with fixed pool
return Executors.newFixedThreadPool(10);
}
}
public void executeTask(Runnable task) {
if (useVirtualThreads) {
Thread.startVirtualThread(task);
} else {
new Thread(task).start();
}
}
}@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
// Optionally enable virtual threads programmatically
Map<String, Object> defaultProperties = new HashMap<>();
defaultProperties.put("spring.threads.virtual.enabled", true);
app.setDefaultProperties(defaultProperties);
ConfigurableApplicationContext context = app.run(args);
// Check threading mode at startup
Environment env = context.getEnvironment();
String mode = Threading.VIRTUAL.isActive(env)
? "Virtual Threads"
: "Platform Threads";
System.out.println("Running with: " + mode);
}
}@SpringBootTest
class ThreadingTests {
@Autowired
private Environment environment;
@Test
@TestPropertySource(properties = "spring.threads.virtual.enabled=true")
void testWithVirtualThreadsEnabled() {
// This test assumes Java 21+
if (isJava21OrLater()) {
assertTrue(Threading.VIRTUAL.isActive(environment));
assertFalse(Threading.PLATFORM.isActive(environment));
}
}
@Test
@TestPropertySource(properties = "spring.threads.virtual.enabled=false")
void testWithPlatformThreads() {
assertTrue(Threading.PLATFORM.isActive(environment));
assertFalse(Threading.VIRTUAL.isActive(environment));
}
private boolean isJava21OrLater() {
return JavaVersion.getJavaVersion()
.isEqualOrNewerThan(JavaVersion.TWENTY_ONE);
}
}@Component
@ConditionalOnProperty(
name = "spring.threads.virtual.enabled",
havingValue = "true"
)
public class VirtualThreadOptimizedService {
public VirtualThreadOptimizedService() {
System.out.println("Using virtual thread optimized implementation");
}
public void performBlockingOperation() {
// This implementation is optimized for virtual threads
// Can safely block without worrying about thread pool exhaustion
}
}
@Component
@ConditionalOnProperty(
name = "spring.threads.virtual.enabled",
havingValue = "false",
matchIfMissing = true
)
public class PlatformThreadService {
public PlatformThreadService() {
System.out.println("Using platform thread implementation");
}
public void performBlockingOperation() {
// This implementation avoids blocking operations
// Uses async/non-blocking patterns
}
}// Good use cases for virtual threads:
// 1. High-concurrency I/O operations
@Service
public class IoService {
public void handleManyRequests() {
// Can handle thousands of concurrent requests
}
}
// 2. Blocking database calls
@Repository
public class UserRepository {
public User findUser(Long id) {
// Blocking JDBC call - virtual threads handle this efficiently
}
}
// 3. REST API calls
@Service
public class ExternalApiClient {
public String callExternalApi() {
// Blocking HTTP call - no problem with virtual threads
}
}// Better with platform threads:
// 1. CPU-intensive operations
@Service
public class ComputationService {
public void heavyCalculation() {
// CPU-bound work - platform threads are more appropriate
}
}
// 2. Thread-local intensive operations
@Service
public class ThreadLocalService {
private ThreadLocal<Context> context = new ThreadLocal<>();
// Heavy thread-local usage may not benefit from virtual threads
}spring.threads.virtual.enabled=trueimport org.springframework.boot.thread.Threading;
import org.springframework.boot.system.JavaVersion;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;