- Multi-threading is a way/process of executing more than one threads concurrently/ simultaneously of same process to complete it effectively at micro level.
- In single processor systems, only a single thread of execution occurs at a given instant of time, but in a java program multiple threads executed which finally increases the utilization of CPU.
- A Java thread is actually a lightweight sub-process or smallest part of a process.
- Multi-threading is also sometimes called Thread-based Multitasking.
- Thread is a smallest executable unit of a process.
- A thread is single sequence of execution that can run independently in an application.
- Thread has its own path of execution in a process.
- A process can have one/multiple threads.
- When we start any Java program, one thread begins running first/immediately, which is called the Main thread of that program. Within the main thread, we can create many other Child threads as per need of the program. These child thread may be user threads as well as daemon threads.The main thread is created automatically by JVM when the program is started. The main thread of Java programs is controlled through an object of Thread class.By using a static method called current Thread ( ), we can get a reference to the thread in which this method is called. Once we have a reference to the main thread, we can control it just like other threads created.
- Every thread has its lifetime.
- Threads of the same process share the memory address of that process i.e. threads are stored inside the memory of a process. As the threads are stored in the same memory space, communication between threads (Inter Thread Communication) is fast. Context switching from one thread to another thread also occurs and is less expensive.
- Each thread normally runs parallel to each other.
- Threads don’t allocate separate memory area to run it, hence it saves memory.
- The CPU quickly switches back and forth between several threads (called Context Switching) to create an illusion that the threads are executing in parallel or at the same time.
- Each instruction sequence for a thread has its own unique flow of control that is independent of all other threads. These independently executed instruction sequences are really a thread.
- Java has built-in support for multi-threading.
- Threads are independent in execution because they all have separate path of execution i.e. if an exception occurs in one thread, it doesn’t affect the execution of other threads.
- All threads of same process, share the common memory.
- Any application can have multiple processes (instances). Each of this process may be of a single thread or multiple threads.
- Java was one of the first languages that has multi-threading facility.
- We can also set different priorities to different Threads but it doesn’t guarantee that higher priority thread will execute first than lower priority thread. Thread scheduler is a program and is the part of operating system that implements thread i.e. when a thread is started, its execution is controlled by Thread Scheduler and JVM doesn’t have any control on its execution.Once a thread pauses its execution, we can’t say/specify when it will get chance again, it depends on thread scheduler of the system.
- A thread is said to be Dead when the processing of the thread is completed normally. After a thread reaches the dead state, then it is not possible to restart it.
- It reduces the maintenance cost of the application.
- It supports maximum resource utilization of the system on which application(s) is running.
- This feature supports concurrency in java i.e. concurrency can be used within a process to implement multiple instances of simultaneous services.
- Multi-threaded programming is very useful in network as well as Internet applications development.
- Multi-threading requires less processing overhead than multi-programming because concurrent threads are able to share common resources more efficiently.
- Multi-threading enables programmers to write very efficient programs that make maximum use of the CPU.
- A multi-threaded web server is one of the best example of multi-threaded programming where they are able to efficiently handle multiple browser requests at a time and handles one request per processing thread (browser).
- The benefit of Java’s multi-threading is that an individual thread can be controlled easily without affecting others i.e. we can pause a thread without stopping other parts/threads of the program. A paused thread can restart again.
- Debugging and testing process of thread program is complex.
- Output of thread program(especially intermediate output) is sometimes unpredictable.
- Context switching in thread program cause process overhead.
- Thread program Increases potential for deadlock occurrence.
- Increased difficulty level in writing thread program.
- Requires more synchronization of shared resources (objects, data).
Types of Thread
There are two types of thread – user thread and daemon thread. We can convert user thread into daemon thread explicitly(when needed) by using setDaemon() method of the thread.
- When a thread application started, user thread is created first and after that, we can create many user threads or daemon threads as per need.
- User threads are threads which are created by the application or user.
- These threads perform the completion of user’s application/jobs.
- These are normally high priority threads.
- These threads are foreground threads.
- JVM (Java Virtual Machine) will not exit completely until all user threads finish their execution. JVM wait for these threads to finish their task.
- These are threads which are mostly created by the JVM as per requirements.
- These threads always run in background.
- These threads perform the completion of system related jobs mainly but indirectly helps in completing the user’s job.
- These threads are used to perform some specific background tasks like garbage collection, clean the application and other house-keeping tasks.
- These threads are normally less priority threads.
- JVM will not wait for these threads to finish their execution completely. JVM will exit as soon as all user threads finish their execution. JVM doesn’t wait for daemon threads to finish their task.
Life Cycle of a Thread/Thread State/Thread Model
The thread exists as an object and have six well-defined states. At any point of time, thread will be in any one of these states. (java.lang.Thread class has one member of enum type called State. All states of a thread are stored in this enum as constants.) These are:-
- When we create an instance of Thread class, a thread is in a new state.
- A thread that has not yet started is supposed to be in this state.
- A new thread begins its life cycle as new state. It remains in this state until the program starts the thread.
- It is also referred to as a born thread.
- It is the first state of thread life cycle.
- After a newly born thread is started, the thread becomes runnable.
- A thread in this state is considered to be executing its task.
- When a thread is created, it doesn’t begin executing immediately rather we first invoke start ( ) method to start the execution of the thread. In this process, the thread scheduler must allocate CPU time to the Thread.
- A thread may also come back into this ready state (when it was stopped for a while during processing time due to some reason)to resume its execution after fulfilling conditions.
- The Java thread is in running state inside JVM.
- Threads are born to run, and a thread is said to be in the running state when it is actually executing.
- A running thread can be suspended, mostly temporarily suspends its activity, due to lack of some signals or other lacking factors.
- A suspended thread can be resumed by regaining required signals or related lacking factors, allowing it to pick up again where it left off.
- In this state, thread waits for another thread to perform a task.
- A suspended thread back to the runnable state only when another thread signals the waiting thread to continue executing.
- A thread will be in this state when wait() or join() method is called.
- A thread may remain in waiting state up to indefinite time until waiting condition is fulfilled.
- A waiting state may be a TIMED_WAITING i.e. It is a runnable thread that can enter into the timed waiting state for a specified interval of time. In this state, a thread is waiting for another thread to perform an action for up to a specified waiting time. A thread in this state transitions back to the runnable state when that time interval expires or when the event it is waiting for occurs.
- A running thread may perform a number of actions. A common example is when the thread performs some type of input or output operations.
- A java thread can be blocked when waiting for a resource normally.
- A thread is said to be in this state when a thread is in deadlock state.
- A runnable thread enters the terminated state when it completes its task normally or otherwise terminates.
- A thread can be terminated, which halts its execution immediately at any given time.
- Once a thread is terminated, it cannot be resumed.
The life-cycle of a thread can be summarized as –
A thread begins as a ready thread using start () method and then enters the running state using run() method when the thread scheduler schedules it. When the thread is prompted by other threads then it returns to the ready state again, or it may wait on a resource, or simply stop for some time. When this happens, the thread enters the waiting/blocked state. To run again from waiting/blocked state, the thread must re-enter the ready state. Finally, the thread will cease its execution after normal completion and entered into the dead state.
The multi-threading system in Java is built upon the Thread Class (having several methods that help in managing threads) and an interface called, Runnable. To create a new thread, we can use Thread class (in the form of inheritance) either extend Thread Class or by implementing/using the Runnable interface.
Thus, a new thread can be created through two ways:-
1. By extending the Thread class
2. By implementing the Runnable Interface (Easiest way to create a thread)
Priority of Threads
- Since a java application shows multi-threading features and hence every Java thread has a unique priority positive integer value that helps the operating system to determine the order in which threads are scheduled/executed during processing time on priority basis.
- A thread with highest priority is chosen first for execution than the thread with lower priority and so on.
- There are two common thread priority methods present in java.lang.Thread class. They are setPriority() and getPriority() methods. Here setPriority() method is used to set a new/change the old priority value of a thread and getPriority() method is used to retrieve the priority value of a thread.
- Java threads priorities lie in the range between MIN_PRIORITY (1) and MAX_PRIORITY (10) but every thread, by default, has NORM_PRIORITY (5).
- Threads with higher priority are more important for a program/system and should be allocated processor time first than lower-priority threads. However, thread priorities cannot guarantee the order in which threads execute and are very much platform dependent.
- Thread priorities are given with positive integer value which decide how one thread should be treated with respect to the others.
- Thread priority decides when to switch from one running thread to another, this process is called context switching.
- A thread can be preempted by a higher priority thread no matter what the lower priority thread is doing. Whenever a higher priority thread wants to run it does.
- The default priority of a thread is same as that of its parent.
There are so many thread methods but some common thread methods used in several thread applications are as follows:-
- getName(): It is used for obtaining a thread’s name as string.
- getPriority(): It is used for obtaining a thread’s priority value from 1 to 10 as integer.
- interrupt(): It stops the running of a thread.
- isAlive(): It is used to check/determine if a thread is still running or not.
- join(): Wait for a thread to terminate. This method is used to join the start of a thread’s execution to end of other thread’s execution such that a thread does not start running until another thread ends. If join() is called on a Thread instance, the currently running thread will block until the Thread instance has finished executing. The join() method waits at most this much milliseconds for this thread to die. Here a timeout of 0 means to wait forever.
- notify(): It wakes up one single thread that called wait() on the same object. Actually the calling notify() does not actually give up a lock on a resource. It tells a waiting thread that that thread can wake up. However, the lock is not actually given up until the notifier’s synchronized block has completed.
- notifyAll(): It wakes up all the threads that called wait() on the same object. The highest priority thread will run first in most of the situation, though not guaranteed. Other things are same as notify() method above.
- run(): Entry point for the thread.
- setName(): It is used for changing or put a new name of a thread.
- sleep(): Suspend/pause/sleep a running thread for a specified period of time in milliseconds and then restart again after that time.
- start(): start a thread by calling its run() method.
- states(): gives thread current states.
- wait(): when we call wait() method, this forces the current thread to wait until some other thread invokes notify() on the same object i.e. It tells the calling thread to give up the lock and go to sleep until some other thread enters the same monitor and calls notify().The wait() method releases the lock prior to waiting and reacquires the lock prior to returning from the wait() method. The wait() method is actually tightly integrated with the synchronization lock.
- yield(): Yield method is used to pause the execution of currently running process so that other waiting thread with the same priority will get CPU to execute. Threads with lower priority will not be executed using yield method. It temporarily stop the execution of currently running threads and gives a chance to the other remaining waiting threads of the same priority to execute. This method is applied mainly when a currently running thread is not doing anything particularly so important and if other threads or processes need to be run having same priority, they should give a chance and run.
Inter Process Communication & Synchronization
440 total views, 2 views today