Professional Documents
Culture Documents
MULTITHREDING For Bca Book
MULTITHREDING For Bca Book
UNIT-4
between multiple programs to complete their execution in real time, while in multi-
threading CPU switches between multiple threads of the same program. Switching
between multiple processes has more context switching cost than switching between
multiple threads of the same program.
3. Processes are heavyweight as compared to threads. They require their own address
space, which means multi-tasking is heavy compared to multithreading.
4. Multitasking allocates separate memory and resources for each process/program
whereas, in multithreading threads belonging to the same process shares the same
memory and resources as that of the process.
Figure: Multitasking
When several users are sharing a multitasking operating system, CPU scheduling and
multiprogramming makes it possible for each user to have at least a small portion of
Multitasking OS and let each user have at least one program in the memory for execution.
Multi threading
Multithreading is different from multitasking in a sense that multitasking allows mul-
tiple tasks at the same time, whereas, the Multithreading allows multiple threads of a single
task (program, process) to be processed by CPU at the same time.
A thread is a basic execution unit which has its own program counter, set of the register
and stack. But it shares the code, data, and file of the process to which it belongs. A process
can have multiple threads simultaneously, and the CPU switches among these threads so fre-
quently making an impression on the user that all threads are running simultaneously.
ET
C
Figure: Multithreading
SV
Benefits of Multithreading
• Multithreading increases the responsiveness of system as, if one thread of the
application is not responding, the other would respond in that sense the user would
not have to sit idle.
• Multithreading allows resource sharing as threads belonging to the same process can
share code and data of the process and it allows a process to have multiple threads at
the same time active in same address space.
• Creating a different process is costlier as the system has to allocate different memory
and resources to each process, but creating threads is easy as it does not require
allocating separate memory and resources for threads of the same process.
4.2 Thread Lifecycle
A thread in Java at any point of time exists in any one of the following states. A thread lies
only in one of the shown states at any instant:
1) New
2) Runnable
3) Blocked
4) Waiting
5) Timed Waiting
6) Terminated
The following figure represents various states of a thread at any instant of time:
ET
C
SV
• It is the responsibility of the thread scheduler to give the thread, time to run.
• A multi-threaded program allocates a fixed amount of time to each individual thread.
Each and every thread runs for a short while and then pauses and relinquishes the CPU
to another thread, so that other threads can get a chance to run. When this happens,
all such threads that are ready to run, waiting for the CPU and the currently running
thread lies in runnable state.
3. Blocked/Waiting state:
• When a thread is temporarily inactive, then it’s in one of the following states:
○○ Blocked
○○ Waiting
• For example, when a thread is waiting for I/O to complete, it lies in the blocked state.
It’s the responsibility of the thread scheduler to reactivate and schedule a blocked/
waiting thread.
• A thread in this state cannot continue its execution any further until it is moved to
ET
runnable state. Any thread in these states do not consume any CPU cycle.
• A thread is in the blocked state when it tries to access a protected section of code that
is currently locked by some other thread. When the protected section is unlocked, the
schedule picks one of the threads which is blocked for that section and moves it to
C
the runnable state. A thread is in the waiting state when it waits for another thread on
a condition. When this condition is fulfilled, the scheduler is notified and the waiting
thread is moved to runnable state.
SV
○○ Because there occurred some unusual erroneous event, like segmentation fault
or an unhandled exception.
• A thread that lies in terminated state does no longer consumes any cycles of CPU.
Creating Threads
• Threading is a facility to allow multiple tasks to run concurrently within a single
process. Threads are independent, concurrent execution through a program, and each
thread has its own stack.
In Java, There are two ways to create a thread:
1) By extending Thread class.
2) By implementing Runnable interface.
Java Thread Benefits
1. Java Threads are lightweight compared to processes as they take less time and re-
source to create a thread.
ET
2. Threads share their parent process data and code
3. Context switching between threads is usually less expensive than between process-
es.
4. Thread intercommunication is relatively easy than process communication.
C
Thread class:
Thread class provide constructors and methods to create and perform operations on a
SV
thread. Thread class extends Object class and implements Runnable interface.
Commonly used Constructors of Thread class:
• Thread()
• Thread(String name)
• Thread(Runnable r)
• Thread(Runnable r, String name)
Commonly used methods of Thread class:
1. public void run(): is used to perform action for a thread.
2. public void start(): starts the execution of the thread. JVM calls the run() method on
the thread.
3. public void sleep(long miliseconds): Causes the currently executing thread to sleep
(temporarily cease execution) for the specified number of milliseconds.
4. public void join(): waits for a thread to die.
5. public void join(long miliseconds): waits for a thread to die for the specified mili-
seconds.
6. public int getPriority(): returns the priority of the thread.
7. public int setPriority(int priority): changes the priority of the thread.
8. public String getName(): returns the name of the thread.
9. public void setName(String name): changes the name of the thread.
10. public Thread currentThread(): returns the reference of currently executing
thread.
11. public int getId(): returns the id of the thread.
12. public Thread.State getState(): returns the state of the thread.
13. public boolean isAlive(): tests if the thread is alive.
14. public void yield(): causes the currently executing thread object to temporarily pause
ET
and allow other threads to execute.
15. public void suspend(): is used to suspend the thread(depricated).
16. public void resume(): is used to resume the suspended thread(depricated).
C
17. public void stop(): is used to stop the thread(depricated).
18. public boolean isDaemon(): tests if the thread is a daemon thread.
SV
19. public void setDaemon(boolean b): marks the thread as daemon or user thread.
20. public void interrupt(): interrupts the thread.
21. public boolean isInterrupted(): tests if the thread has been interrupted.
22. public static boolean interrupted(): tests if the current thread has been interrupted.
Naming Thread
The Thread class provides methods to change and get the name of a thread. By default,
each thread has a name i.e. thread-0, thread-1 and so on. But we can change the name of the
thread by using setName() method. The syntax of setName() and getName() methods are
given below:
public String getName(): is used to return the name of a thread.
public void setName(String name): is used to change the name of a thread.
Extending Thread
The first way to create a thread is to create a new class that extends Thread, and then to
create an instance of that class. The extending class must override the run( ) method, which
is the entry point for the new thread. It must also call start( ) to begin execution of the new
thread.
Sample java program that creates a new thread by extending Thread:
// Create a second thread by extending Thread
class NewThread extends Thread
{
NewThread()
{ // Create a new, second thread
super(“Demo Thread”);
System.out.println(“Child thread: “ + this);
ET
start(); // Start the thread
}
// This is the entry point for the second thread.
C
public void run()
{
SV
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(“Child thread is exiting”);
}
}
public class ExtendThread
{
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);
ET
Thread.sleep(1000);
}
}
C
catch (InterruptedException e)
{
SV
Child Thread: 2
Main Thread: 3
Child Thread: 1
Child thread is exiting.
Main Thread: 2
Main Thread: 1
Main thread is exiting.
The child thread is created by instantiating an object of NewThread, which is derived
from Thread. The call to super( ) is inside NewThread. This invokes the following form of
the Thread constructor:
public Thread(String threadName)
Here, threadName specifies the name of the thread.
Implementing Runnable
ET
• The easiest way to create a thread is to create a class that implements the Runnable
interface.
• Runnable abstracts a unit of executable code. We can construct a thread on any object
C
that implements Runnable.
• To implement Runnable, a class need only implement a single method called run( ),
which is declared as:
SV
Sample Output:
(output may vary based on processor speed and task load)
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
Child thread is exiting.
ET
Main Thread: 2
Main Thread: 1
Main thread is exiting.
C
In a multithreaded program, often the main thread must be the last thread to finish run-
ning. In fact, for some older JVMs, if the main thread finishes before a child thread has
completed, then the Java run-time system may “hang.” The preceding program ensures that
SV
the main thread finishes last, because the main thread sleeps for 1,000 milliseconds between
iterations, but the child thread sleeps for only 500 milliseconds. This causes the child thread
to terminate earlier than the main thread.
Choosing an Approach
The Thread class defines several methods that can be overridden by a derived class. Of
these methods, the only one that must be overridden is run(). This is, of course, the same
method required when we implement Runnable. Many Java programmers feel that classes
should be extended only when they are being enhanced or modified in some way. So, if we
will not be overriding any of Thread’s other methods, it is probably best simply to implement
Runnable.
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.”);
}
}
public class MultiThreadDemo
{
public static void main(String args[])
{
new NewThread(“One”); // start threads
new NewThread(“Two”);
new NewThread(“Three”);
try
{
// wait for other threads to end
ET
Thread.sleep(10000);
}
catch (InterruptedException e)
C
{
System.out.println(“Main thread Interrupted”);
SV
}
System.out.println(“Main thread exiting.”);
}
}
The output from this program is shown here:
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.
ET
Three exiting.
Main thread exiting.
As we can see, once started, all three child threads share the CPU. The call to sleep(10000)
in main(). This causes the main thread to sleep for ten seconds and ensures that it will finish
C
last.
Using isAlive( ) and join( )
SV
We want the main thread to finish last. In the preceding examples, this is accomplished
by calling sleep( ) within main( ), with a long enough delay to ensure that all child threads
terminate prior to the main thread. However, this is hardly a satisfactory solution, and it also
raises a larger question: How can one thread know when another thread has ended?
Two ways exist to determine whether a thread has finished or not.
• First, we can call isAlive( ) on the thread. This method is defined by Thread.
Syntax:
final boolean isAlive( )
The isAlive( ) method returns true, if the thread upon which it is called is still running. It
returns false, otherwise.
• Second, we can use join() to wait for a thread to finish.
Syntax:
final void join( ) throws InterruptedException
This method waits until the thread on which it is called terminates. Its name comes from
the concept of the calling thread waiting until the specified thread joins it.
Sample Java program using join() to wait for threads to finish.
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
ET
}
// This is the entry point for thread.
public void run()
C
{
SV
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 + “ is exiting.”);
}
}
public 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());
ET
// wait for threads to finish
try
{
C
System.out.println(“Waiting for threads to finish.”);
ob1.t.join();
SV
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 is exiting.”);
}
}
Sample output:
(output may vary based on processor speed and task load)
New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
One: 5
New thread: Thread[Three,5,main]
Two: 5
Thread One is alive: true
Thread Two is alive: true
Thread Three is alive: true
Waiting for threads to finish.
Three: 5
One: 4
ET
Two: 4
Three: 4
One: 3
C
Two: 3
Three: 3
SV
One: 2
Two: 2
Three: 2
One: 1
Two: 1
Three: 1
One is exiting.
Two is exiting.
Three is exiting.
Thread One is alive: false
Thread Two is alive: false
Thread Three is alive: false
Main thread is exiting.
As we can see, after the calls to join( ) return, the threads have stopped executing.
4.3 Synchronization
• Synchronization in java is the capability to control the access of multiple threads to
any shared resource.
• Java Synchronization is better option where we want to allow only one thread to
access the shared resource.
• 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. Java provides unique, language-
level support for it.
• Key to synchronization is the concept of the monitor (also called a semaphore).
• 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
ET
will be suspended until the first thread exits the monitor.
• These other threads are said to be waiting for the monitor. A thread that owns a monitor
can reenter the same monitor if it so desires.
• Approaches:
C
○○ Using synchronized Method
○○ Using synchronized Statement
SV
Thread.sleep(1000);
}
SV
catch(InterruptedException e)
{
System.out.println(“Interrupted”);
}
System.out.println(“]”);
}
}
Thread t;
public Caller(Callme targ, String s)
{
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
public void run()
{
target.call(msg);
}
ET
}
{
Callme target = new Callme();
Caller ob1 = new Caller(target, “Hello”);
Caller ob2 = new Caller(target, “Synchronized”);
Caller ob3 = new Caller(target, “World”);
// wait for threads to end
try
{
ob1.t.join();
ob2.t.join();
ob3.t.join();
}
catch(InterruptedException e)
{
System.out.println(“Interrupted”);
}
}
}
Sample Output:
Hello[Synchronized[World]
]
]
As we can see, by calling sleep( ), the call( ) method allows execution to switch to another
thread. This results in the mixed-up output of the three message strings.
In this program, nothing exists to stop all three threads from calling the same method, on
the same object, at the same time. This is known as a race condition, because the three threads
ET
are racing each other to complete the method.
This example used sleep( ) to make the effects repeatable and obvious. In most situations,
a race condition is more subtle and less predictable, because we can’t be sure when the con-
text switch will occur. This can cause a program to run right one time and wrong the next.
C
To fix the preceding program, we must serialize access to call(). That is, we must restrict
its access to only one thread at a time. To do this, we simply need to precede call()’s definition
SV
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println(“Interrupted”);
}
System.out.println(“]”);
}
} ET
class Caller implements Runnable
{
String msg;
C
Callme target;
Thread t;
SV
System.out.println(“Interrupted”);
}
}
}
Output:
[Hello]
[Synchronized]
[World]
Using synchronized Statement
While creating synchronized methods within classes that we create is an easy and effec-
tive means of achieving synchronization, it will not work in all cases. We have to put calls to
the methods defined by the class inside a synchronized block.
Syntax:
synchronized(object)
{
// statements to be synchronized
}
Here, object is a reference to the object being synchronized. A synchronized block en-
sures that a call to a method that is a member of object occurs only after the current thread has
successfully entered object’s monitor.
Here is an alternative version of the preceding example, using a synchronized block with-
in the run( ) method:
// This program uses a synchronized block.
class Callme
{
void call(String msg)
ET
{
System.out.print(“[“ + msg);
try
C
{
Thread.sleep(1000);
SV
}
catch (InterruptedException e)
{
System.out.println(“Interrupted”);
}
System.out.println(“]”);
}
}
class Caller implements Runnable
{
String msg;
Callme target;
Thread t;
ob3.t.join();
}
catch(InterruptedException e)
{
System.out.println(“Interrupted”);
}
}
}
Here, the call( ) method is not modified by synchronized. Instead, the synchronized state-
ment is used inside Caller’s run( ) method. This causes the same correct output as the preced-
ing example, because each thread waits for the prior one to finish before proceeding.
Sample Output:
[Hello]
ET
[World]
[Synchronized]
Priority of a Thread (Thread Priority):
C
Each thread has a priority. Priorities are represented by a number between 1 and 10. In
most cases, thread schedular schedules the threads according to their priority (known as pre-
SV
emptive scheduling). But it is not guaranteed because it depends on JVM specification that
which scheduling it chooses.
3 constants defined in Thread class:
1. public static int MIN_PRIORITY
3) notifyAll() method
Wakes up all threads that are waiting on this object’s monitor. Syntax:
SV
try
{
pc.producer();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable()
{
ET
public void run()
{
try
C
{
pc.consumer();
SV
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
class InterThread_Example
{
public static void main(String arg[])
{
final Client c = new Client();
new Thread()
{
public void run()
{
c.withdraw(15000);
}
}.start();
new Thread()
{
public void run()
{
c.deposit(10000);
}
}.start();
new Thread()
{
public void run()
{
ET
c.deposit(10000);
}
}.start();
C
}
SV
class Client
{
int amount = 10000;
{
System.out.println(“Insufficient Balance waiting for deposit.”);
try
{
wait();
} catch (Exception e)
{
System.out.println(“Interruption Occured”);
}
}
this.amount -= amount;
ET
System.out.println(“Detected amount: “ + amount);
System.out.println(“Balance amount : “ + this.amount);
}
C
{
System.out.println(“Going to deposit “ + amount);
this.amount += amount;
System.out.println(“Available Balance “ + this.amount);
System.out.println(“Transaction completed.\n”);
notify();
}
}
4.5 Daemon thread
Daemon thread is a low priority thread that runs in background to perform tasks such as
garbage collection. Daemon thread in java is a service provider thread that provides services
to the user thread. Its life depend on the mercy of user threads i.e. when all the user threads
dies, JVM terminates this thread automatically.
There are many java daemon threads running automatically e.g. gc, finalizer etc.
• It provides services to user threads for background supporting tasks. It has no role in
life than to serve user threads.
• Its life depends on user threads.
• It is a low priority thread.
The command jconsole typed in the command prompt provides information about the
loaded classes, memory usage, running threads etc.
The purpose of the daemon thread is that it provides services to user thread for back-
ground supporting task. If there is no user thread, why should JVM keep running this thread.
That is why JVM terminates the daemon thread if there is no user thread.
Properties:
• They cannot prevent the JVM from exiting when all the user threads finish their
execution.
ET
• JVM terminates itself when all user threads finish their execution
• If JVM finds running daemon thread, it terminates the thread and after that shutdown
itself. JVM does not care whether Daemon thread is running or not.
• It is an utmost low priority thread.
C
Methods for Java Daemon thread by Thread class
The java.lang.Thread class provides two methods for java daemon thread.
SV
Method Description
public void setDaemon(boolean status) used to mark the current thread as daemon
thread or user thread.
public boolean isDaemon() used to check that current is daemon.
// Java program to demonstrate the usage of setDaemon() and isDaemon() method.
public class DaemonThread extends Thread
{
public void run()
{
// Checking whether the thread is Daemon or not
if(Thread.currentThread().isDaemon())
{
System.out.println(“This is Daemon thread”);
}
else
{
System.out.println(“This is User thread”);
}
}
public static void main(String[] args)
{
DaemonThread t1 = new DaemonThread();
DaemonThread t2 = new DaemonThread();
DaemonThread t3 = new DaemonThread();
// Setting user thread t1 to Daemon
ET
t1.setDaemon(true);
// starting all the threads
t1.start();
C
t2.start();
t3.start();
SV
System.out.println(“user thread work”);
}
}
public static void main(String[] args){
TestDaemonThread1 t1=new TestDaemonThread1();//creating thread
TestDaemonThread1 t2=new TestDaemonThread1();
TestDaemonThread1 t3=new TestDaemonThread1();
t1.setDaemon(true);//now t1 is daemon thread
t1.start();//starting threads
t2.start();
t3.start();
}
ET
}
The following program is another example for daemon thread.
class DaemonThread1_example extends Thread{
C
public void run(){
System.out.println(“Name: “+Thread.currentThread().getName());
SV
System.out.println(“Daemon: “+Thread.currentThread().isDaemon());
}
public static void main(String[] args){
TestDaemonThread2 t1=new TestDaemonThread2();
TestDaemonThread2 t2=new TestDaemonThread2();
t1.start();
t1.setDaemon(true);//will throw exception here
t2.start();
}
}
public void run() {
System.out.println(Thread.currentThread().getName());
SV
}
public static void main(String[] args) {
ThreadGroup_example runnable = new ThreadGroup_example();
ThreadGroup tg1 = new ThreadGroup(“Parent ThreadGroup”);
Thread t1 = new Thread(tg1, runnable,”one”);
t1.start();
Thread t2 = new Thread(tg1, runnable,”two”);
t2.start();
Thread t3 = new Thread(tg1, runnable,”three”);
t3.start();
System.out.println(“Thread Group Name: “+tg1.getName());
tg1.list();
}
}
Sample Output:
one
two
three
Thread Group Name: Parent ThreadGroup
java.lang.ThreadGroup[name=Parent ThreadGroup,maxpri=10]
Thread [one,5,Parent ThreadGroup]
Thread [two,5,Parent ThreadGroup]
ET
Thread [three,5,Parent ThreadGroup]
Methods of ThreadGroup class
There are many methods in ThreadGroup class. A list of important methods are given
below.
C
Method Description
SV
void destroy() destroys this thread group and all its sub groups.
Thread.sleep(10);
}
catch (InterruptedException ex)
{
System.out.println(“Exception encounterted”);
}
}
}
}
public class ThreadGroup_example
{
public static void main(String arg[])
{