I'm curious as well. Once you can use an ExecutorService with virtual threads, the gap seems a bit thin.
The best I can tell is that coroutines are a bit lighter weight (in terms of what state is managed) and have a bit simpler usage out-of-the-box.
But I've not used them myself so maybe I'm not seeing how big of advantage those are or perhaps there's more to it than that?