In a Spring app, you could use the Task Execution abstraction.
https://docs.spring.io/spring/docs/5.2.7.RELEASE/spring-framework-reference/integration.html#scheduling
There are a few different implementations you can use, but you probably want ThreadPoolTaskExecutor. I think it would be most similar to what you're describing. It will basically run tasks in a different thread.
You can also use Spring's @Async functionality. This is a way to execute long running tasks without blocking the worker threads in your application server. I'd say that it's a bit of syntactic sugar on top of the task execution abstraction I first mentioned. It will in fact use a default TaskExecutor, or you can configure your own.
This article walks through how to use it.
https://www.baeldung.com/spring-async
There is also the JVM's java.util.concurrent package. You could use this directly, although if you're using Spring already there's not much reason to do that. Just wanted to mention that you can avoid the Spring abstractions if you do not want to/cannot have a dependency on Spring. It will just be more work to set things up and make sure you're doing it correctly.
Hope that helps!