Multi Threaded Programming: Unit - Iv
Multi Threaded Programming: Unit - Iv
UNIT – IV
Multi threading:
It is the process of implementing two or more parts of a program to run
concurrently. Each part of such a program is called a thread, and each thread defines a
separate path of execution, thus multithreading is a specialized form of multitasking.
Process-based Multitasking(Multiprocessing)
Thread-based Multitasking(Multithreading)
Process-based Multitasking
Each process has its own address in memory i.e. each process allocates separate
memory area.
Process is heavyweight.
Cost of communication between the process is high.
Switching from one process to another require some time for saving and loading
registers, memory maps, updating lists etc.
For example, process-based multitasking enables you to run the Java compiler at
the same time that you are using a text editor.
Page 1
Thread-based Multitasking
Threads share the same address space.
Thread is lightweight.
Cost of communication between the thread is low.
If you have programmed for operating systems such as Windows, then you are
already familiar with multithreaded programming.
For instance, a text editor can format text at the same time that it is printing, as
long as these two actions are being performed by two separate threads.
1. New
2. Runnable
3. Running
4. Non-Runnable (Blocked)
5. Terminated
New Thread New Born
stop
start
stop Dea
Active d
Running Runnable Stat
Thread
yield
Suspend
resume
stop
Sleep
Wait notify
Idle Thread
(Not Runnable) Blocked
1) New
The thread is in new state if you create an instance of Thread class but before the
invocation of start() method.
2) Runnable
The thread is in runnable state after invocation of start() method, but the thread
scheduler has not selected it to be the running thread.
3) Running
The thread is in running state if the thread scheduler has selected it.
4) Non-Runnable (Blocked)
This is the state when the thread is still alive, but is currently not eligible to run.
5) Terminated
A thread is in terminated or dead state when its run() method exits.
How to create thread
Thread class:
Thread class provide constructors and methods to create and perform operations on a
thread. Thread class extends Object class and implements Runnable interface.
Thread()
Thread(String name)
Thread(Runnable r)
Thread(Runnable r,String name)
When a Java program starts up, one thread begins running immediately. This is
usually called the main thread of the program, because it is the one that is executed
when the program begins.
The main thread is important for two reasons:
• It is the thread from which other “child” threads will be spawned.
• Often, it must be the last thread to finish execution because it performs
various shutdown actions.
Although the main thread is created automatically when the program is started, it can
be controlled through a Thread object. To do so, we must obtain a reference to it by
calling the method currentThread( ), which is a public static member of Thread.
Its general form is shown here:
static Thread currentThread( )
It returns a reference to the thread in which it is called.
Program: Write a java program to illustrate Controlling the main Thread.
class CurrentThreadDemo {
public static void main(String args[])
{ Thread t =
Thread.currentThread();
System.out.println("Current thread: " + t);
// change the name of the thread
t.setName("My Thread");
System.out.println("After name change: " + t);
try {
for(int n = 5; n > 0; n--)
{ System.out.println(n
);
Thread.sleep(1000);
}
} catch (InterruptedException e)
{ System.out.println("Main thread
interrupted");
}
}
}
Output:
Current thread: Thread[main,5,main]
After name change: Thread[My Thread,5,main]
5
4
3
2
1
Output:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
Create a Thread by implementing Runnable interface.
If your class is intended to be executed as a thread then you can achieve this by
implementing a Runnable interface. You will need to follow three basic steps −
Step 1
Implement a run() method provided by a Runnable interface. This method provides an
entry point for the thread and you will put your complete business logic inside this
method.
Following is a simple syntax of the run() method
− public void run( ) { }
Step 2
As a second step, you will instantiate a Thread object using the following constructor −
Thread(Runnable threadObj, String threadName);
Where, threadObj is an instance of a class that implements the Runnable interface
and threadName is the name given to the new thread.
Step 3
Once a Thread object is created, you can start it by calling start() method, which
executes a call to run( ) method.
Following is a simple syntax of start() method
− void start();
Program: Write a java program to create threads by implementing Runnable interface.
// Create a second thread.
class NewThread implements Runnable {
Thread t;
NewThread() {
// Create a new, second thread
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start(); // Start the thread
}
// This is the entry point for the second thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e)
{ System.out.println("Child
interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ThreadDemo {
public static void main(String args[]) {
new NewThread(); // create a new thread
try {
for(int i = 5; i > 0; i--)
{ System.out.println("Main Thread: " +
i); Thread.sleep(1000);
}
} catch (InterruptedException e)
{ System.out.println("Main thread
interrupted.");
}
System.out.println("Main thread exiting.");
}
}
Output:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
Output:
New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
New thread: Thread[Three,5,main]
One: 5
Two: 5
Three: 5
One: 4
Two: 4
Three: 4
One: 3
Three: 3
Two: 3
One: 2
Three: 2
Two: 2
One: 1
Three: 1
Two: 1
One exiting.
Two exiting.
Three exiting.
Main thread exiting.
Thread Priorities
Thread priorities are used by the thread scheduler to decide when each thread
should be allowed to run. The higher-priority threads get more CPU time than lower-
priority threads.
Program: Write a java program to illustrate the use of isAlive() and join() methods.
class NewThread implements Runnable {
String name; // name of thread
Thread t;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 5; i > 0; i--)
{ System.out.println(name + ": " +
i); Thread.sleep(1000);
}
} catch (InterruptedException e)
{ System.out.println(name + "
interrupted.");
}
System.out.println(name + " exiting.");
}
}
class DemoJoin {
public static void main(String args[])
{ NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
NewThread ob3 = new NewThread("Three");
System.out.println("Thread One is alive: " + ob1.t.isAlive());
System.out.println("Thread Two is alive: " + ob2.t.isAlive());
System.out.println("Thread Three is alive: " + ob3.t.isAlive());
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch (InterruptedException e)
{ System.out.println("Main thread
Interrupted");
}
System.out.println("Thread One is alive: " + ob1.t.isAlive());
System.out.println("Thread Two is alive: " + ob2.t.isAlive());
System.out.println("Thread Three is alive: " + ob3.t.isAlive());
System.out.println("Main thread exiting.");
}
}
Output:
New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
New thread: Thread[Three,5,main]
Thread One is alive: true
Thread Two is alive: true
Thread Three is alive: true
Waiting for threads to finish.
One: 5
Two: 5
Three: 5
One: 4
Two: 4
Three: 4
One: 3
Two: 3
Three: 3
One: 2
Two: 2
Three: 2
One: 1
Two: 1
Three: 1
Two exiting.
Three exiting.
One exiting.
Thread One is alive: false
Thread Two is alive: false
Thread Three is alive: false
Main thread exiting.
Thread Synchronization
When two or more threads need access to a shared resource, they need some
way to ensure that the resource will be used by only one thread at a time. The process
by which this is achieved is called synchronization.
The synchronization is mainly used to
1. To prevent thread interference.
2. To prevent inconsistency problem.
Principle: The key principle of synchronization is the concept of the monitor.
Monitor:
A monitor is an object that is used as a mutually exclusive lock, or mutex. Only
one thread can own a monitor at a given time. When a thread acquires a lock, it is said to
have entered the monitor. All other threads attempting to enter the locked monitor will
be suspended until the first thread exits the monitor. These other threads are said to be
waiting for the monitor.
Using Synchronized Methods
To enter an object’s monitor, just call a method that has been modified with the
synchronized keyword. While a thread is inside a synchronized method, all other
threads that try to call it (or any other synchronized method) on the same instance have
to wait. To exit the monitor and relinquish control of the object to the next waiting
thread, the owner of the monitor simply returns from the synchronized method.
Example:
Suppose two different threads are performing two operations writing and
reading a same file at a time. The file should be available to one thread at a time. Hence
the two methods, on which the threads are trying to access a file, must be synchronized.
synchronized public void write(char ch) {
;
}
synchronized public char read( ) {
;
;
}
Interthread Communication
In the above concept, the threads are unconditionally blocked other threads from
asynchronous access to certain methods.
Threads also provide a secondary benefit: they do away with polling. Polling is
usually implemented by a loop that is used to check some condition repeatedly. Once
the condition is true, appropriate action is taken. This wastes CPU time.
To avoid polling, Java includes an elegant inter-thread communication
mechanism via the wait( ), notify( ), and notifyAll( ) methods.
Inter-thread communication or Co-operation is all about allowing
synchronized threads to communicate with each other.
Cooperation (Inter-thread communication) is a mechanism in which a thread is
paused running in its critical section and another thread is allowed to enter (or lock) in
the same critical section to be executed. It is implemented by following methods.
These methods are implemented as final methods in Object, so all classes have them.
Note: All three methods can be called only from within a synchronized context.
1. wait() method
Causes current thread to release the lock and wait until either another thread
invokes the notify() method or the notifyAll() method for this object, or a specified
amount of time has elapsed.
Method Description
public final void wait() throws
waits until object is notified.
InterruptedException
public final void wait(long timeout) throws waits for the specified amount
InterruptedException of time.
2. notify( ) method
Wakes up a single thread that is waiting on this object's monitor. If any threads
are waiting on this object, one of them is chosen to be awakened.
Syntax: public final void notify()
3. notifyAll( ) Method
Wakes up all threads that are waiting on this object's monitor.
Syntax: public final void notifyAll( )
Program: Write a java program that correctly implements producer-consumer problem using
the concept of inter thread communication.
Source Code:
class Q
{
boolean valueSet=false;
int n;
synchronized int get()
{
if(!valueSet)
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("Exception is:"+e);
}
System.out.println("got:"+n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n)
{
if(valueSet)
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("\n Exception in put:"+e);
}
this.n=n;
valueSet=true;
System.out.println("\n put:"+n);
notify();
}
}
class Producer implements Runnable
{
Q q;
Producer(Q q)
{
this.q=q;
new Thread(this,"Producer").start();
}
public void run()
{
int i=0;
while(true)
q.put(i++);
}
}
class Consumer implements Runnable
{
Q q;
Consumer(Q q)
{
this.q=q;
new Thread(this,"Consumer").start();
}
public void run()
{
while(true)
q.get();
}
}
class ProducerConsumer
{
public static void main(String args[])
{
Q q=new Q();
new
Producer(q);
new Consumer(q);
}
}
Output:
put: 1
got: 1
put: 2
got: 2
put: 3
got: 3
put: 4
got: 4
put: 5
got: 5
Suspending, Resuming, and Stopping Threads