or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

admin-jmx.mdansi-support.mdaot-native-image.mdapplication-info.mdavailability.mdbootstrap.mdbootstrapping.mdbuilder.mdcloud-platform.mdconfiguration-annotations.mdconfiguration-data.mdconfiguration-properties.mdconversion.mddiagnostics.mdenvironment-property-sources.mdindex.mdjson-support.mdlifecycle-events.mdlogging.mdorigin-tracking.mdresource-loading.mdretry-support.mdssl-tls.mdstartup-metrics.mdsupport.mdsystem-utilities.mdtask-execution.mdthreading.mdutilities.mdvalidation.mdweb-support.md
tile.json

threading.mddocs/

Spring Boot Thread Package

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.

Threading Enum

Threading

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)

    • Active when virtual threads are not enabled
    • Uses the JVM's native thread implementation
    • Available on all Java versions
  • VIRTUAL - Lightweight virtual threads (Project Loom)

    • Active when spring.threads.virtual.enabled=true AND running Java 21+
    • Provides lightweight, scalable threading
    • Requires Java 21 or later

Usage Examples

Checking Active Threading Mode

@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");
        }
    }
}

Enabling Virtual Threads

# application.properties
spring.threads.virtual.enabled=true
# application.yml
spring:
  threads:
    virtual:
      enabled: true

Conditional Bean Registration Based on Threading

@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;
    }
}

Runtime Threading Detection

@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");
    }
}

Custom Threading Decision Logic

@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();
        }
    }
}

Application Startup Configuration

@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);
    }
}

Testing with Different Threading Modes

@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);
    }
}

Conditional Component Based on Threading

@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
    }
}

Virtual Threads Benefits and Considerations

Benefits of Virtual Threads

  • High Scalability: Can create millions of virtual threads
  • Low Overhead: Minimal memory footprint per thread
  • Simplified Code: Write synchronous-looking code that scales
  • Better Resource Utilization: Automatic yielding during blocking operations

When to Use Virtual Threads

// 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
    }
}

When to Stick with Platform 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
}

Requirements

  • Java Version: Virtual threads require Java 21 or later
  • Property: Set spring.threads.virtual.enabled=true
  • Both conditions must be met for virtual threads to activate

Import Statements

import 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;