In Java program, you create threads but they are not executed by Java alone. Java takes the help of the underlying OS to execute them. To allocate microprocessor time and to supervise all the threads' execution, the OS comes with Thread Scheduler. The entire responsibility of maintaining the sequence of execution of threads, where which thread should be given first preference than the other, lies with the thread scheduler. The scheduling depends on the algorithm of the scheduler. Many types of algorithms exist like preemptive and time slicing with round robin etc. It is a very complex algorithm that executes many times in a given time.
Java Thread Scheduler
The scheduler maintains a pool of threads. When Java thread is started calling start() method, it joins the pool of waiting threads. For deciding processor allocation for each waiting thread, the scheduler takes many aspects into consideration.
1. Priority of thread
2. Waiting time of thread
3. Nature of thread
The JVM is based on preemptive and priority based scheduling algorithm. The thread with more priority is given first preference than the thread with less priority. The thread with more priority relinquishes (empties) the thread with less priority that is being executed. If the threads of equal priority are in the pool, the waiting time is taken in consideration. Nature of threads sometimes affects. The daemon threads are given less importance and are executed only when no other thread is available for execution.
When JVM starts executing a Java program, it creates a few threads for the execution.
1. main is a method for us, but main is a thread for JVM. The execution starts with main thread.
2. Garbage collector is a daemon thread that comes into action before every thread.
3. Event Dispatcher is a thread which will take care of events raised by the components like click of a button etc.
4. There is one more, Timer thread, which maintains the time for methods like sleep() etc.
When a thread is started with start() method, the Java thread joins the pool of waiting threads. It does not mean the scheduler should give the processor time immediately. "Joins" means, it is guaranteed of getting processor time, but at what time depends on the decision of the scheduler managed by the OS. When a thread joins, the scheduler is executed by the OS and makes a table of threads' sequence to allocate processor time. When a sleep() method is called, the thread is removed from the active pool, then again the scheduler is executed to make the table as there comes imbalance in the waiting threads. And executed again when the thread joins the pool when the sleep() time is over. For this reason, the scheduler executes a number of times when a thread joins, yields, stops or leaves (when blocked or dies) the pool.