Java provides many ways to create and write multithreaded code.
There are 2 main types of threads in Java:
Platform Threads are native OS threads that Java wraps to provide a simple and consistent API for us to use (Java’s whole thing is write once run everywhere!). Comes with the resource expense of OS threads, but are great for CPU bound tasks.
Virtual Threads are ‘threads’ fully managed by the JVM, are extremely lightweight and good for I/O bound tasks but come with additional computational overhead. They share the same API as Platform Threads.

Java Thread States

Java provides its own abstraction over OS threads & their states.
This is then mapped to the actual platform thread & states.

Diagram of Native Thread Signalling Methods

Diagram of ObjectMonitor Signalling Methods

A thread can be in 1 of 7 states at any given time. 2 of which are just when it is created and when it is terminated. So that leaves us with 5 interesting states.

  • Runnable
    • Ready - Ready to be executed, waiting for its time on the CPU
    • Running - Currently executing
  • Waiting - Waits for some other thread to notify it to wake up and become runnable again
  • Timed Waiting - Same as waiting, but it won’t wait forever, becoming runnable after a set amount of time
  • Blocked - Waiting for control of a monitor

Multithreading Constructs

Java has many multithreading constructs to help us manage & coordinate threads and shared objects!

Synchronisation Constructs (Used for controlling access to shared objects)

Threading Constructs

Coordination Constructs

  • CountDownLatch
  • Semaphore

Concurrent Collections

  • ConcurrentHashMap
  • Collections.synchronizedList()
  • BlockingQueue

Atomic Variables

  • AtomicLong
  • LongAdder
  • AtomicReference