Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExecutorService configuration with virtual threads

In a service I have 2 executorServices for different tasks:

  1. get user transactions (50-100 threads, queue 300)
  2. get user family (10-50 threads, queue 100)

It was easy to monitoring threads and adding resources and implement logic "skip this task if queue is full".

How this should be migrated to java 21? Is this logic "skip this task if queue is full" still can be implemented?

Example:

private ThreadPoolTaskExecutor getExecutor(AsyncProperties executorProperties, ContextDataDecorator contextDataDecorator) {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setVirtualThreads(executorProperties.isVirtual());
    executor.setTaskDecorator(contextDataDecorator);
    executor.setCorePoolSize(executorProperties.getPoolSize());
    executor.setMaxPoolSize(executorProperties.getPoolSize());
    executor.setThreadNamePrefix(executorProperties.getThreadNamePrefix());
    executor.setRejectedExecutionHandler((runnable, threadPoolExecutor) -> log.warn("Task {} was skipped by executor {}", runnable, threadPoolExecutor));
    if (executorProperties.hasQueueCapacity()) {
        executor.setQueueCapacity(executorProperties.getQueueCapacity());
    }
    executor.initialize();
    return executor;
}

configs:

transactions.executor:
    pool-size: 100
    thread-name-prefix: transactions-async-executor-
    queue-capacity: 200
    virtual: true
family.executor:
    pool-size: 50
    queue-capacity: 100
    thread-name-prefix: family-async-
like image 245
Olga grts Avatar asked Aug 02 '26 15:08

Olga grts


1 Answers

The closest to Spring's ThreadPoolTaskExecutor (if TaskExecutor implementation is what really needed) is org.springframework.core.task.SimpleAsyncTaskExecutor:

    SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
    executor.setVirtualThreads(true);
    executor.setTaskDecorator(contextDataDecorator);
    executor.setThreadNamePrefix(executorProperties.getThreadNamePrefix());
    return executor;

As virtual threads are used, core and max pool sizes are not applicable - there is no thread poll per se, each task is executed on a dedicated throw-away virtual thread which terminates upon task completion. Queue is not applicable as well, and the execution cannot be rejected.

It is assumed that the restrictions to ThreadPoolTaskExecutor pool sizes serve the purpose of preserving system resources, and are not the purpose of restricting simultaneous access to limited resources like JDBC Connections, what @Holger discussed in his comment. If this is a case then the above solution won't work, please then consult Cannot limit the concurrency of servlet requests using Spring Boot virtual threads with Tomcat SO thread, in particular a part which discusses a recommended way to use Semaphore in combination with Spring AOP.

Finally, keep in mind that virtual threads are daemons, so graceful shutdown of tasks, running by them, is not supported out of the box. SO thread Spring boot with java 21 virtual threads - is there a way to terminate gracefully? discusses that.

like image 103
igor.zh Avatar answered Aug 05 '26 06:08

igor.zh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!