Threads
In Java, all threads are created during the startup of the application. This is because creating threads is a resource intensive process.
Every thread also has memory allocated in RAM and will remain until the thread is alive.
It's important to understand how stacks work under each thread. See code execution page to understand how the stack is used for code execution.
Threads are created and are in an infinite loop waiting for tasks.
When the main thread of the application receives the request, it just passes the request to the task queue from which the already created threads will pick up the work.

Once the thread is created, it's only task is to pick up tasks from the task queue. The code of the thread starts with this loop.
This is a blocking queue, which means when the queue is empty, the logic behind the take method will put the thread to sleep until anything is added to the queue.

Starting multiple threads
JVM always creates the main thread itself and if the application code creates more threads, it will just execute the thread creation code in the main thread.
When a new thread is created, JVM will create a new thread object in the heap memory and will also create a corresponding OS thread.
Inter Thread Communication
Threads can communicate between each other using static, volatile, atomic and synchronized concepts.
- static - Shared variable that can be accessed from multiple threads.
- volatile - Means the variable is constantly being updated hence must not be read from CPU cache instead from memory.
- atomic - These are special variables where the update is allowed to be performed only when you pass the previous value and if the previous passed value is really the previous known value of the variable. Otherwise the update is rejected.
- synchronous - A block of code that can be executed by only one thread at a time. Other threads are simply paused until then.
OS Threads vs JVM Threads
For each JVM thread has a corresponding OS thread. This means the thread scheduling is managed by OS. JVM only queues tasks for the threads which are then scheduled and executed by the OS.
