There are two basic strategies for using Thread objects to create a concurrent application.

  • To directly control thread creation and management, simply instantiate Thread each time the application needs to initiate an asynchronous task.
  • To abstract thread management from the rest of your application, pass the application’s tasks to an executor.

Starting a thread:

new Thread().start()

new Thread(Runnable r).start()

Declaring a thread:

  • extend Thread, override run() method
  • implement Runnable, implement run() method,


Due to shared memory space, threads can interleave

– interference: 2 threads concurrently modifying the same object produce an unpredictable outcome

– memory inconsistency: 2 threads concurrently using the same object, one modifying and one reading its state produce an unpredictable outcome


– a monitor mechanism using a lock object

– problems caused: deadlock, starvation

The monitor mechanism

– a monitor is a mechanism that implements thread safety and it consists of

  • lock object (mutex) that ensures mutually exclusive access for a thread to a block of code
  • condition variables – container of threads that acquired the same lock object and that are either waiting for a notification that a condition is fulfilled (Object.wait / Condition.await) or can notify other threads that that condition is fulfilled (Object.notify / Condition.signal)

Atomic action

= cannot be interleaved, has no side effects

– read & write are atomic for all variables (except long and double)

– read & write are atomic for all volatile variables


– changes to a volatile variable are always visible to other threads. What’s more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change

– more efficient than synchronized


interface Lock

– works just like synchronized keyword

– plus information about the state of the lock, non blocking lock, can abandon locking

interface Executor

– starts threads: executorObj.execute(runnableObj);

concurrent collections:

–  provide atomic operations on collections

CopyOnWriteArraySet, CopyOnWriteArrayList

– write creates a clone of the collection so Iterators see snapshots


– concurrent sorted set


– putIfAbsent, remove, replace


– extends Queue, facilitates operations on full or empty queues