Don't forget ExecutorService and the whole concept of sending chunks of work back and forth across synchronizing queues. Best way to write concurrent code in any language IMO, analogous to go's channels/goroutines and erlang's whatever they're called.
Java.util.concurrent.ExecutorService is great. Coupling it with Hazelcast is truly great in creating a dynamic cluster that performs parallel distributed work with ease. One of the pains in setting up server cluster in AWS is the cluster discovery and membership maintenance. Hazelcast does all those automatically.
Also AtomicInt,Float,Long make life easier when dealing with threaded programs.