My understanding is that threads in theory are executed in parallel. JVM decides; when a resource is available which thread to pick from the waiting thread queue (based on some
Since java 8 this has become very easy using CompletableFuture :
CompletableFuture.runAsync(runnable3) .thenRunAsync(runnable1) .thenRunAsync(runnable2);