Threading concept is very important in Java Programming language. A thread is a sequential path of code execution within a program. And each thread has its own local variables, program counter and lifetime
Threading
Introduction:
Threading
concept is very important in Java Programming language. A thread is a sequential
path of code execution within a program. And each thread has its own local
variables, program counter and lifetime. In single threaded runtime environment,
operations are executes sequentially. That means next operation can execute only
when the previous one is complete. But a Multithreading term allows more than
one thread to be running concurrently with in a program. Sometimes thread can be
referred as lightweight processes because in a program they exist in a common
memory space and that?s why they can share both data and code. By using
threading we can increased the speed of any application.
Parallel Processing:
Parallel
processing simultaneously and concurrently execution of two or more processes of
same computer program by using two or more processors. Parallel processing makes
a program execution faster because there are more CPUs running it. Parallel
processing requires two or more interconnected processors, each of which
executes a different portion of task. Parallel processing differs from
multitasking, in which a single CPU executes several programs at once.
Multitasking & Multithreading:
Multitasking
allow to execute more than one tasks at the same time, a task being a program.
In multitasking only one CPU is involved but it can switches from one program to
another program so quickly that's why it gives the appearance of executing all
of the programs at the same time. Multitasking allow processes (i.e. programs)
to run concurrently on the program. For Example running the spreadsheet program
and you are working with word processor also.
Multitasking is running heavyweight processes by a single OS.
Multithreading is running multiple lightweight processes in a single process/
task or program. For Example, When you used a word processor you performs a many
different tasks such as printing, formatting text, spell checking and so on.
Multithreaded software treats each process as a separate program.
Advantages of multithreading over multitasking: Some advantages of multithreading over multitasking are :
- Threads share the same address space.
- Context switching between threads is usually less
expensive than between processes.
- Cost of communication between threads is relatively low.
Main Thread: When any standalone application is running, it firstly execute the main() method runs in a one thread, called the main thread. If no other threads are created by the main thread, then program terminates when the main() method complete its execution. The main thread creates some other threads called child threads. The main() method execution can finish, but the program will keep running until the all threads have complete its execution.
Thread Creation: In Java, an object of the Thread class can represent a thread. Thread can be implementing by one of two ways:
- Extending the java.lang.Thread Class
- Implementing the java.lang.Runnable Interface
Extending the
java.lang.Thread Class
For creating a thread a class have to extend the Thread Class. For creating a thread by this procedure you have to follow these steps:
- Extend the java.lang.Thread Class.
- Override the run() method in the subclass from the Thread class to define the code executed by the thread.
- Create an instance of this subclass. This subclass may call a Thread class constructor by subclass constructor.
- Invoke the start() method on the instance of the class to make the thread eligible for running.
The following program demonstrates the thread creation way by extending Thread Class:
class MyThread extends Thread{ MyThread(String s){ super(s); start(); } public void run(){ for(int i=0;i<10;i++){ System.out.println("Thread Name :"+Thread.currentThread().getName()); try{ Thread.sleep(100); }catch(Exception e){} } } } public class RunThread{ public static void main(String args[]){ System.out.println("Thread Name :"+Thread.currentThread().getName()); MyThread m1=new MyThread("My Thread 1"); MyThread m2=new MyThread("My Thread 2"); } }
C:\j2se6\thread>javac
RunThread.java C:\j2se6\thread>java RunThread Thread Name :main Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 C:\j2se6\thread> |
Implementing the java.lang.Runnable Interface
The procedure for creating threads by implementing the Runnable Interface is as follows:
- A Class implements the Runnable Interface, override the run() method to define the code executed by thread. An object of this class is Runnable Object.
- Create an object of Thread Class by passing a Runnable object as argument.
- Invoke the start() method on the instance of the Thread class.
The following program demonstrates the thread creation way by implenting the Runnable interface:
class MyThread1 implements Runnable{ Thread t; MyThread1(String s){ t=new Thread(this,s); t.start(); } public void run(){ for(int i=0;i<10;i++){ System.out.println("Thread Name :"+Thread.currentThread().getName()); try{ Thread.sleep(100); }catch(Exception e){} } } } public class RunableThread{ public static void main(String args[]) { System.out.println("Thread Name :"+Thread.currentThread().getName()); MyThread1 m1=new MyThread1("My Thread 1"); MyThread1 m2=new MyThread1("My Thread 2"); } }
Output of the Program is:
C:\j2se6\thread>javac
RunableThread.java C:\j2se6\thread>java RunableThread Thread Name :main Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 Thread Name :My Thread 1 Thread Name :My Thread 2 C:\j2se6\thread> |
Thread Constructors: Several
constructors are available for creating new Thread instances.
Thread()
Thread(String)
Thread(Runnable)
Thread(Runnable,String)
Thread(ThreadGroup,String)
Thread(ThreadGroup,Runnable)
Thread(ThreadGroup,Runnable,String)
Thread(ThreadGroup, Runnable, String, long)
ThreadGroup? All threads belongs to an instance of the ThreadGroup Class. ThreadGroup is used to represent a group of threads. ThreadGroups are hierarchical: there is only one root ThreadGroup and it contains all other thread and groups and each subgroups can contain other groups and threads. All thread have only one thread group. And all thread groups (except the root thread group) belongs to exactly one parent thread group. Threads can access the only belonging thread group.
When a new ThreadGroup is created, it
is added as a member of existing ThreadGroup.
If a thread x in group1, and executes the code:
ThreadGroup group2=new ThreadGroup(?group2?);
Then the newly formed group2 comes under group1. If you want a parent group other than default then you have to specify the parent group at the time of creation.
ThreadGroup group2=new ThreadGroup(group2,?group3?); 0
Then newly formed group3 comes under the group2.
Some important methods are:
-
getName() ? This method is used to retrieve the name of particular group.
ThreadGroup g=new ThreadGroup(?RoseIndia?);
String gname=g.getName();
1 -
getParent() ? This method is used to retrieve the name of parent threadgroup of sub group.
ThreadGroup group=group3.getParent();
-
activeGroupCount() ? This method returns the number of active thread group in a particular thread group and all its subgroups.
int size=group.activeGroupCount();
-
getThreadGroup() ? This method is used to know the thread is belong to which thread group.
ThreadGroup group=threadx.getThreadGroup();
2 -
activeCount() ? This method returns the number of active threads in a particular thread group and all its subgroups.
Life Cycle of Threads: When
you are programming with threads, understanding the life cycle of thread is very
valuable. While a thread is alive, it is in one of several states. By invoking
start() method, it doesn?t mean that the thread has access to CPU and start
executing straight away. Several factors determine how it will proceed.
Different states of threads are-
- New state ? After the creations of Thread
instance the thread is in this state but before the start() method
invocation. At this point, the thread is considered not alive.
- Runnable (Ready-to-run) state ? A thread
start its life from Runnable state. A thread first enters runnable state
after the invoking of start() method but 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. There are several ways
to enter in Runnable state but there is only one way to enter in Running
state: 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.
- Non-Runnable state ? A running thread can enter to any non-runnable state, depending on the circumstances. A thread cannot enters directly to the running state from non-runnable state, firstly it goes to runnable state. Some non-runnable states are as follows:
- Sleeping ? On this state, the thread is
still alive but its 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.
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.
- Blocked for joint completion ? The thread
can come on this state because of waiting the completion of another thread.
- Blocked for lock acquisition ? The thread
can come on this state because of waiting to acquire the lock of an object.
Different Thread States 3
Some Important Methods:
- final boolean isAlive() ? This method is
used to find out the thread is alive or not.
- static void yield() ? By invoking this
method the current thread pause its execution temporarily and allow other
threads to execute.
- final void join() throws InterruptedException
and final void join(long millisec) throws InterruptedException ?
These two methods invoked on a thread will wait and not return until either
the thread has completed or it is timed out respectively.
- void interrupt() ? The method interrupt the
threads on which it is invoked.
- final void notify() and final void notifyAll() ? Invoking these method on an object wakes up a single thread that is waiting on the lock of this object. That the object lock is not relinquished when the notifying thread invokes the notify() method. The notifying thread relinquishes the lock at its own discretion, and the awakened thread will not be able to run until the notifying thread relinquishes the object lock
4
Thread
Priorities:
Thread scheduler can use the thread priorities to
determine the execution schedule of threads. Thread gets the ready-to-run state
according to their priorities. The thread scheduler provides the CPU time to
thread of highest priority thread in the ready-to-run state.
Priorities
are integer values from 1 (lowest priority given by the constant Thread.MIN_PRIORITY)
to 10 (highest priority given by the constant Thread.MAX_PRIORITY). The
default priority is 5(Thread.NORM_PRIORITY).
setPriority()
? This is method is used to set the priority of thread.
getPriority() ? This method is used to get the priority of thread.
Lock: This term refers to the access granted to
a particular thread that can access the shared resources. At any given time,
only one thread can hold the lock and thereby have access to the shared
resource. Every object in Java has build-in lock that only comes in action when
the object has synchronized method code. By associating a shared resource with a
Java object and its lock, the object can act as a guard, ensuring synchronized
access to the resource. Only one thread at a time can access the shared resource
guarded by the object lock.
Since there is one lock per object, if one thread has acquired the lock, no
other thread can acquire the lock until the lock is not released by first
thread. Acquire the lock means the thread currently in synchronized method and
released the lock means exits the synchronized method. Remember the following
points related to lock and synchronization:
- Only methods (or blocks) can be synchronized, Classes and variable cannot
be.
- Each object has just one lock.
- All methods in a class need not to be synchronized. A class can have both
synchronized and non-synchronized methods.
- If two threads wants to execute a synchronized method in a class, and both
threads are using the same instance of the class to invoke the method then
only one thread can execute the method at a time.
- If a class has both synchronized and non-synchronized methods, multiple
threads can still access the class's non-synchronized methods. If you have
methods that don't access the data you're trying to protect, then you don't
need to synchronize them. Synchronization can cause a hit in some cases (or
even deadlock if used incorrectly), so you should be careful not to overuse
it.
- If a thread goes to sleep, it holds any locks it has?it doesn't release
them.
- A thread can acquire more than one lock. For example, a thread can enter a
synchronized method, thus acquiring a lock, and then immediately invoke a
synchronized method on a different object, thus acquiring that lock as well.
As the stack unwinds, locks are released again.
- You can synchronize a block of code rather than a method.
- Constructors cannot be synchronized
There are two ways to synchronized the execution of code: 6
- Synchronized Methods
- Synchronized Blocks (Statements)
Synchronized Methods: If any method is
specified with the keyword synchronized then this method of an object is only
executed by one thread at a time. A any thread want to execute the synchronized
method, firstly it has to obtain the objects lock. Acquire the method is simply
by calling the method. If the lock is already held by another thread, then
calling thread has to wait.
Synchronized methods are useful in those situations where methods can manipulate
the state of an object in ways that can corrupt the state if executed
concurrently. Stack implementations usually define the two operations push and
pop of elements as synchronized, that?s why pushing and popping are mutually
exclusive operations. For Example if several threads were sharing a stack, if
one thread is popping the element on the stack then another thread would not be
able to pushing the element on the stack.
The following program demonstrates the synchronized method:
public class SynThread{ public static void main(String args[]){ Share s=new Share(); MyThread m1=new MyThread(s,"Thread1"); MyThread m2=new MyThread(s,"Thread2"); MyThread m3=new MyThread(s,"Thread3"); } } class MyThread extends Thread{ Share s; MyThread(Share s,String str){ super(str); this.s=s; start(); } public void run(){ s.doword(Thread.currentThread().getName()); } } class Share{ public synchronized void doword(String str){ for(int i=0;i<5;i++){ System.out.println("Started :"+str); try{ Thread.sleep(100); }catch(Exception e){} } } }
Output of the program is: 7
C:\j2se6\thread>javac
SynThread.java C:\j2se6\thread>java SynThread Started :Thread1 Started :Thread1 Started :Thread1 Started :Thread1 Started :Thread1 Started :Thread3 Started :Thread3 Started :Thread3 Started :Thread3 Started :Thread3 Started :Thread2 Started :Thread2 Started :Thread2 Started :Thread2 Started :Thread2 C:\j2se6\thread> |
Synchronized Blocks (Statements): A synchronized statement is another way to create synchronized code. Synchronized statements must specify the object that provides the intrinsic lock. The synchronized block allows execution of arbitrary code to be synchronized on the lock of an arbitrary object.
General form of synchronized block is:
synchronized (object reference expression)
{
code block..
}
The following program demonstrates the synchronized block: 8
public class SynStatement{ public static void main(String args[]){ Share s=new Share(); MyThread m1=new MyThread(s,"Thread1"); MyThread m2=new MyThread(s,"Thread2"); MyThread m3=new MyThread(s,"Thread3"); } } class MyThread extends Thread{ Share s; MyThread(Share s,String str){ super(str); this.s=s; start(); } public void run(){ s.doword(Thread.currentThread().getName()); } } class Share{ public void doword(String str){ synchronized(this){ for(int i=0;i<5;i++){ System.out.println("Started :"+str); try{ Thread.sleep(100); }catch(Exception e){} } } } }
Output of the program is:
C:\j2se6\thread>javac SynStatement.java C:\j2se6\thread>java SynStatement Started :Thread1 Started :Thread1 Started :Thread1 Started :Thread1 Started :Thread1 Started :Thread3 Started :Thread3 Started :Thread3 Started :Thread3 Started :Thread3 Started :Thread2 Started :Thread2 Started :Thread2 Started :Thread2 Started :Thread2 C:\j2se6\thread> |
Deadlock: A situation where a thread is waiting for an object lock that holds by second thread, and this second thread is waiting for an object lock that holds by first thread, this situation is known as Deadlock.
The following program demonstrates the deadlock situation: 9
public class DeadDemo{ public static void main(String args[]){ String s1="Dead"; String s2="Lock"; MyThread1 m=new MyThread1(s1,s2); MyThread2 m1=new MyThread2(s1,s2); } } class MyThread1 extends Thread{ String s1; String s2; MyThread1(String s1, String s2){ this.s1=s1; this.s2=s2; start(); } public void run(){ while(true){ synchronized(s1){ synchronized(s2){ System.out.println(s1+s2); } } } } } class MyThread2 extends Thread{ String s1; String s2; MyThread2(String s1,String s2){ this.s1=s1; this.s2=s2; start(); } public void run(){ while(true){ synchronized(s2){ synchronized(s1){ System.out.println(s2+s1); } } } } }
Output of the program is:
C:\j2se6\thread>javac
DeadDemo.java C:\j2se6\thread>java DeadDemo DeadLock DeadLock DeadLock DeadLock DeadLock DeadLock DeadLock DeadLock LockDead LockDead LockDead LockDead LockDead LockDead LockDead DeadLock DeadLock DeadLock DeadLock DeadLock DeadLock DeadLock ......... ......... C:\j2se6\thread> |
Daemon Threads: In Java, any thread can be a Daemon thread. Daemon threads are service providers for other threads or objects running in the same process as the daemon thread. Daemon threads are used for background supporting tasks and are only needed while normal threads are executing. If normal threads are not running and remaining threads are daemon threads then the interpreter exits. 0
setDaemon(true/false)
? This method is used to specify that a thread is daemon thread.
public boolean isDaemon() ? This
method is used to determine the thread is daemon thread or not.
The following program demonstrates the Daemon Thread:
public class DaemonThread extends Thread { public void run() { System.out.println("Entering run method"); try { System.out.println("In run Method: currentThread() is"+ Thread.currentThread()); while (true) { try { Thread.sleep(500); } catch (InterruptedException x) { } System.out.println("In run method: woke up again"); } } finally { System.out.println("Leaving run Method"); } } public static void main(String[] args) { System.out.println("Entering main Method"); DaemonThread t = new DaemonThread(); t.setDaemon(true); t.start(); try { Thread.sleep(3000); } catch (InterruptedException x) { } System.out.println("Leaving main method"); } }
Output of this program is: 1
C:\j2se6\thread>javac
DaemonThread.java C:\j2se6\thread>java DaemonThread Entering main Method Entering run method In run Method: currentThread() isThread[Thread-0,5,main] In run method: woke up again In run method: woke up again In run method: woke up again In run method: woke up again In run method: woke up again In run method: woke up again Leaving main method C:\j2se6\thread> |