In this chapter, we will cover the following topics:
- Using immutable objects when possible
 - Avoiding deadlocks by ordering locks
 - Using atomic variables instead of synchronization
 - Holding locks for as short time as possible
 - Delegating the management of threads to executors
 - Using concurrent data structures instead of programming yourselves
 - Taking precautions using lazy initialization
 - Using the fork/join framework instead of executors
 - Avoiding the use of blocking operations inside a lock
 - Avoiding the use of deprecated methods
 - Using executors instead of thread groups
 - Using streams to process big data sets
 - Other tips and tricks