This section discusses how (and why) to use Java's multithreaded programming capabilities to perform concurrent processing. It also compares and contrasts concurrent programming with Java threads (this topic) with parallel programming using the Java fork/join framework (the next topic). This section also explains how to deal with race conditions, the bane of the multithreaded developer.
See http://courses.coreservlets.com/Course-Materials/java.html for the complete tutorial series (Programming with Java 8) and associated code. That site also lets you download PDF files of each lecture for saving or printing, and includes exercises and exercise solutions for each of the topics.