From race conditions to virtual threads: write correct, fast, scalable concurrent Java with hands-on examples