Any threading solution will work. Virtual threads give you the same effect as an unbounded thread pool, but with less overhead. Coroutines are similar, but typically require library support.
If you're getting a timeout exception, my best guess at a solution is to ensure you're using a connection pool with a sufficient max number of connections. Your concurrency is limited by the max number of connections, which could lead to a timeout when your threads are waiting for a connection from the pool.