Which collections should be used in a multi-threaded environment?

The first option is to turn a regular collection into a synchronized one by using the corresponding Collections.synchronized*() method. This is the most general and basic method, which creates a wrapper that synchronizes all operations using synchronized.

If the collection is primarily used for reading, a better performance alternative is CopyOnWriteArrayList and the related CopyOnWriteArraySet. Thread safety is achieved by copying the internal array whenever a modification is made, while the original array remains immutable. Program order is maintained by marking the internal array as volatile.

The third option involves using concurrent collections:
  • Non-blocking hash tables such as ConcurrentSkipListMap, ConcurrentHashMap and ConcurrentSkipListSet (which is based on a hash table under the hood).
  • Non-blocking queues like ConcurrentLinkedQueue and ConcurrentLinkedDeque.
  • A broad range of different blocking queues.