Basic understanding of
Thread and Multi Threading
A
thread is an individual process that has its own call stack. In Java, there is
one call stack per thread. There
is one default thread which is main method thread as every java program must
have one main method so the main thread will always be there and it is
created automatically. When your main method starts, the JVM assigns a thread
for this main method and assigns it a call stack.
Thread behavior is much depends upon the machine it can vary from one machine to other.
Thread behavior is much depends upon the machine it can vary from one machine to other.
Multithreading
refers to two or more threads executing within a single program. Every thread in Java is created
and controlled by the java.lang.Thread class.
A Java program can have many threads, and these threads can run concurrently, either
asynchronously or synchronously.
Confusion between
Multitasking or Multiprocessing and Multi Threading
Multitasking
is about running the multiple programs or tasks concurrently which shares the
same CPU. Multithreading is a advance concept of Multitasking which subdivides
the single program in multiple threads and these threads can run
concurrently.
Understand
this with a simple example
Example:-If we open ms word, music
player and Internet browser in a computer concurrently, this is known to be Multitasking
and if we open ms word and write something in it and auto spell check process
is also checking the spelling concurrently so it is multithreading.
So
if we talk about the java then we mainly have to deal with Multithreading.
Multitasking is mainly concerned with OS.
Defining or Creating a Thread
A
thread can be defined with two ways
·
By
extending Thread class.
·
By
implementing Runnable interface.
In
both the ways one thing is common and that is of overriding or defining the run
() method. The main code which needs to be executed in a new thread is written
in the run () method as: run {
//Action
goes here
}
Creating thread by extending Thread
class
In this method one normal class
extends the inbuilt class thread and override its run () method with the code
required by that particular thread.
·
Create one
class which extends the thread class.
·
Override the
run method and put lines of code inside thread method that will be perform by
thread.
·
Create an
object of class which we created with extending the thread class and call the
start() method to execute the thread.
Example:-
class A extends Thread
{
public void run()
{
System.out.println("Thread
A");
for(int
i=1;i<=5;i++)
{
System.out.println("From
thread A i = " + i);
}
System.out.println("Exit
from A");
}
}
class B extends Thread
{
public void run()
{
System.out.println("Thread
B");
for(int
i=1;i<=5;i++)
{
System.out.println("From
thread B i = " + i);
}
System.out.println("Exit
from B");
}
}
public class Thread_Class
{
public static void
main(String[] args)
{
new
A().start(); //creating A class thread object and calling run
method
new
B().start(); //creating B class thread object and calling run
method
System.out.println("End
of main thread");
}
}
This
is a simple example of creating thread by extending the Thread class.
Now
the question arises that why we call start() method and what the difference
between start() and run() method.
Difference between start() method and run() method
Main difference is that when program calls start()
method a new Thread is created and
code inside run() method is executed in new Thread
while if you call run() method directly no new Thread is created and code
inside run() will execute on current Thread. Another difference
between start and run in Java thread is that you cannot call start()
method twice on thread object. Once started, second call of start
() will throw IllegalStateException in
Java while you can call run () method twice.
Thread Created by implementing the thread interface(Example)
package demo;
public class testing implements
Runnable {
public
void run() {
System.out.println("Hello Run
--->");
delay(500);
}
public
static void main(String args[]){
testing
testing = new testing();
Thread
thd = new Thread(testing); //This is the difference between Extending
Thread and implementing runnable.
thd.run();
thd.run();
}
public
void delay(long timeMiliSec)
{
try{
Thread.sleep(timeMiliSec);
}
catch(Exception
e)
{
e.printStackTrace();
}
}
}
Different stages or
states of Thread
- New state :- After the
creation and before the start() method call, The thread is in this state.
At this point, the thread is considered not alive.
- Runnable (Ready-to-run) state:- When we invoke the
start() method for a thread then
the thread enters into the Runnable state. A
thread can return to this state after either running, waiting, sleeping or
coming back from blocked state also. On this state a thread is waiting for
a turn on the processor.
- Running state:- A thread is in
running state that means the thread is currently executing(Executing the
code written in the run() method). There are several ways to enter in runnable
state but there is only one way to enter in running state that is when the
scheduler select a thread from runnable pool.
- Dead state:- A thread can be considered dead when its run() method completes. If any thread comes on this state that means it cannot ever run again.
- Blocked:- A thread can enter in this state because of waiting the resources that are hold by another thread.
- Sleeping:- On this state,
the thread is still alive but it is not runnable, it might be return to
runnable state later, if a particular event occurs. On this state a thread
sleeps for a specified amount of time. You can use the method sleep( )
to stop the running state of a thread.
static void sleep(long millisecond) throws InterruptedException - Waiting for Notification:- A thread waits for notification from another thread.
The thread sends back to runnable state after sending notification from
another thread.
final void wait(long timeout) throws InterruptedException
final void wait(long timeout, int nanos) throws InterruptedException
final void wait() throws InterruptedException
- Blocked on I/O:- The thread
waits for completion of blocking operation. A thread can enter on this
state because of waiting I/O resource. In that case the thread sends back
to runnable state after availability of resources.
Some
common methods of thread java.lang.thread
Class
1. currentThread( ):- Returns an
object reference to the thread in which it is invoked. IT shows the thread
name, priority and sub folder of the thread. The threads name and priority can
be changed with setName() and setPriority() method but thread subfolder cannot be
changed. The by default priority of thread is 5. It can be set from 1 to 10 values.
2.
getName( ):- Retrieve the name of
the thread object or instance.
3.
start(
):- Start the thread by
calling its run method.
4.
run(
):- This method is the
entry point to execute thread, Contains the code for thread execution.
5.
sleep(
):-Suspends a thread for a
specified amount of time (in milliseconds).
6. isAlive( ):- This method is used to determine the thread is running or
not.
7.
activeCount(
):- This method returns
the number of active threads in a particular thread group and all its
subgroups.
8.
interrupt(
):- The method interrupt
the threads on which it is invoked.
9.
yield(
):-By invoking this method the
current thread pause its execution temporarily and allow other threads to
execute.
10.
join(
):- This method and
join(long millisec) Throws InterruptedException. These two methods
are invoked on a thread. These are not returned until either the thread has
completed or it is timed out respectively.
Stopping a Thread from Executing or InterruptedStop()
A thread that’s completes the run()
method is moved to the dead state. But you should be able to recognize when a
thread will get interrupted out of running state but not be sent back to either
runnable or dead.
In order for the thread to respond to the stop flag the thread has to be running. A thread is in a non-runnable state if
In order for the thread to respond to the stop flag the thread has to be running. A thread is in a non-runnable state if
·
Its
sleep
method is invoked.
·
The thread
calls the
wait
method to wait for a specific
condition to be satisfied.
·
The thread
is blocking on I/O.
If you invoke stop() method on a thread
then the thread should not be in a non
runnable state. If a thread is in a non runnable
state means sleep() methos is called on it then stop() methos will have no
impact on it until the sleep duration will complete or we can call interrupt
method for interrupting the state of the tread as a process of stop() method.
Now when a thread is in a
sleep() or wait() method, calling interrupt() on that thread breaks out of the
sleep or wait and throws an InterruptedException. Ensuring this
exception propagates all the way back up to the exit of the run() method is the
simplest means of stopping a thread. Since the run() method is not declared to
throw any checked exceptions, the InterruptedException needs to be caught and
wrapped in an un-checked exception (such as a Runtime Exception).
Difference
between yield() and sleep() methods
yield():- Allows
the current thread to release its lock from the object and scheduler gives the lock of the object
to the other thread with same priority.sleep():- Allows the thread to go to sleep state for x milliseconds. When a thread goes into sleep state it doesn’t release the lock.
Difference between wait() and sleep() methods
wait():- This method comes under the java.lang.object class and allows the current thread to release its lock from the object and scheduler gives the lock of the object to the other thread with same priority. A waited thread only be reactivated by calling the notify() or notifyAll() method.
sleep():- This method comes under the java.lang.thread class and allows the thread to go to sleep state for x milliseconds. When a thread goes into sleep state it doesn’t release the lock. It will be automatically reactivated after the specified time given in mille second in its sleep() method
Some
common methods of thread java.lang.object
Class
Java uses a process of inter thread
communication to avoid the drawbacks of pooling. To understand it more clearly
lets understand a simple producer and consumer example. Suppose we have two
threads, one for consuming and other for producing. The producer should wait
before producing more data for consumer to consume the data already produced.
In pooling, This situation results in waste of CPU time because producer check
the consumer before producing the data and consumer check the producer for more
data. To avoid this situation, Java gives three final methods in Object class so that all classes can
have them for interposes communication.
- wait( ) tells the
calling thread to give up the monitor and go to sleep until some other
thread enters the same monitor and calls notify( ). - notify( ) wakes up the first thread that called wait( ) on the same object.
- notifyAll( ) wakes up all the
threads that called wait( ) on the same object. The
highest priority thread will run first.
All
these three methods should be called from the synchronized block/method in java
otherwise it can give the IllegalMonitorStateException
and lead to a race condition between wait() and notify() methods. When
a thread running in a synchronized method of an object is calling the wait()
method of the same
object, that thread releases the lock of the object and is added to that object's waiting
queue and also forces the thread to release its lock. This means that it must
own the lock of an object before calling the wait()
method of that (same) object. Hence the thread must be in one of the object's synchronized
methods or synchronized
block before calling wait().
When a thread invokes an object's
notify()
or notifyAll() method, one or all of the threads in its waiting
queue are removed from the waiting queue to the entry
queue. They then actively contend for the object's lock,
and the one that gets the lock goes on to execute. If no threads are waiting in the
waiting queue, then notify() and notifyAll()
have no effect. Before calling the notify()
or notifyAll() method of an object, a thread must own the lock
of the object. Hence it
must be in one of the object's synchronized methods or synchronized
block.Why/When should we call the wait,notify(),notifyAll() method()
If a thread does not want to execute a block of code until a particular state to be achieved. It wants to wait until a particular state to be achieved. The reason to call notify() or notifyAll() method is that the thread will signal others that "a particular state has been achieved". The state is a communication channel between threads and it must be shared mutable state.
We can understand this by a simple example as one thread read data from a buffer and one thread write data into buffer. The reading data thread needs to wait until the writing data thread completly write a block data into the buffer. The wirting data thread needs to wait until the reading data thread completly read the data from the buffer. If wait(), notify(), and notifyAll() methods can be called by a ordinary method , the reading thread calls wait() and the thread is being added to waiting queue . At just the same moment, the writing thread calls notify() to signal the condition changes. The reading thread misses the change and waits forever. Hence, they must be called inside a synchronized method or block which is mutually exclusive.
Volatile Keyword in java
The meaning and use of the
volatile keyword is very interesting and confusing in java as volatile keyword
guarantees that reads from the variable always reflects the most up to update
value. Any
way Volatile keyword in Java is used as an
indicator to Java compiler and Thread that do not cache value of this
variable and always read it from main memory.
How volatile is
different from synchronized
Synchronized is a block or function access modifier and volatile is field
modifier
Difference
between notify() and notifyAll() methodsnotify():-wakes up the first thread that called wait( ) on the same object.
notifyAll():-wakes up all the threads that called wait( ) on the same object. The
highest priority thread will run first.
Daemon threads
Daemon thread are service provider threads run in the background, these not used to run the application code generally. JVM does not wait for the daemon threads to complete their execution if all user threads have completed their execution.
Daemon thread can be created by using setDaemon(boolean value) method. To check whether a thread is a Daemon thread or a user thread use isDaemon() method. By default every thread is a user thread.
Example of the Daemon thread is the Garbage Collector run by JVM to reclaim the unused memory by the application. The Garbage collector code runs in a Daemon thread which terminates as all the user threads are done with their execution.