0% found this document useful (0 votes)
23 views

Java Notes 5

Uploaded by

Abhishek
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views

Java Notes 5

Uploaded by

Abhishek
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

Chapter 6

Threads and Multithreading in Java


by Debasis Samanta

CONTENTS
• Introduction
• Basics of a thread
o Creating and Running a Thread
o Life cycle of threads
o Status of a Thread
• Synchronization and Inter-Thread Communication
o Synchronization
o Inter-thread Communication
• Thread Groups and Daemon
• Practice Questions
• Assignment

• Q&A

Introduction
Multi-threading means multiple flow of control. Multi-threading programming is a conceptual
paradigm for programming where one can divide a program into two or more processes which
can be run in parallel. There are two main advantages of multi-threading : Fist, program with
multiple threads will, in general, result in better utilization of system resources, including the
CPU, because another line of execution can grab the CPU when one line of execution is blocked.
Second, there are several problems better solved by multiple threads. For example, we can
easily write a multi-threaded program to show animation, play music, display documents, and
down load files from the network at the same time.
Java is a multi-threaded language. Java allows to write a program where more than one
processes can be executed concurrently within the single program. Java's threads are often
referred to as light weight threads, which means that they run in the same memory space.
Because Java threads run in the same memory space, they can easily communicate among
themselves because an object in one thread can call a method in another thread without any
overhead from the operating system. In this Tutorial we will learn how to do multi-threaded
programming in Java.

Basics of a thread
As with the Java concepts, everything about thread are defined in a class Thread. The Thread
class encapsulates all of the control one will need over threads. The Thread class is our only link
to manage how threads behave. In this Section, we will learn about : how to create and run a
thread, the life cycle of a thread, and the thread controlling methods.

Creating and Running a Thread


There are two ways to define a thread: one is sub classing Thread and other is using the
Runnable interface.
Using the sub classing thread : With this method, we have to define a class as a sub class of
the Thread class. This sub class should contain a body which will be defined by a method run().
This run() method contains the actual task that the thread should perform. An instance of this sub
class is then to be created by a new statement, followed by a call to the thread's start() method to
have the run() method executed. Let us consider the Illustration 6.1 which includes a program to
create there individual threads that each print out their own " Hello World !" string.

Illustration 6.1 // Creating and running threads using s


ub classing Thread //

/* Creating three threads using the class Thread and then running them concurrentl
y. */
class ThreadA extends Thread{
public void run( ) {
for(int i = 1; i <= 5; i++) {
System.out.println("From Thread A with i = "+ -1*i);
}
System.out.println("Exiting from Thread A ...");
}
}

class ThreadB extends Thread {


public void run( ) {
for(int j = 1; j <= 5; j++) {
System.out.println("From Thread B with j= "+2* j);
}
System.out.println("Exiting from Thread B ...");
}
}
class ThreadC extends Thread{
public void run( ) {
for(int k = 1; k <= 5; k++) {
System.out.println("From Thread C with k = "+ (2*k-1));
}
System.out.println("Exiting from Thread C ...");
}
}

public class Demonstration_111 {


public static void main(String args[]) {
ThreadA a = new ThreadA();
ThreadB b = new ThreadB();
ThreadC c = new ThreadC();
a.start();
b.start();
c.start();
System.out.println("... Multithreading is over ");
}
}

OUTPUT:
From Thread A with i = -1
From Thread A with i = -2
From Thread A with i = -3
From Thread B with j= 2
From Thread A with i = -4
From Thread A with i = -5
Exiting from Thread A ...
... Multithreading is over
From Thread C with k = 1
From Thread B with j= 4
From Thread B with j= 6
From Thread B with j= 8
From Thread B with j= 10
Exiting from Thread B ...
From Thread C with k = 3
From Thread C with k = 5
From Thread C with k = 7
From Thread C with k = 9
Exiting from Thread C ...

In the above simple example, three threads (all of them are of some type) will be executed
concurrently. Note that a thread can be directed to start its body by start() method.
Using the Runnable interface : A second way to create threads is to make use of the Runnable
interface. With this approach, first we have to implement the Runnable interface.[Runnable
interface is already defined in the system package java.lang with a single method run() as below
:

public interface Runnable {


public abstract void run( );
} ]

When we will create a new thread, actually a new object will be instantiated from this Runnable
interface as the target of our thread, meaning that the thread will look for the code for the run( )
method within our object's class instead of inside the Thread's class. This is illustrated with an
example where two processes Brother and Sister will be executed simultaneously.

Illustration 6.2

/* Creating three threads using the Runnable interface and then running them concu
rrently. */
class ThreadX implements Runnable{
public void run( ) {
for(int i = 1; i <= 5; i++) {
System.out.println("Thread X with i = "+ -1*i);
}
System.out.println("Exiting Thread X ...");
}
}

class ThreadY implements Runnable {


public void run( ) {
for(int j = 1; j <= 5; j++) {
System.out.println("Thread Y with j = "+ 2*j);
}
System.out.println("Exiting Thread Y ...");
}
}
class ThreadZ implements Runnable{
public void run( ) {
for(int k = 1; k <= 5; k++) {
System.out.println("Thread Z with k = "+ (2*k-1));
}
System.out.println("Exiting Thread Z ...");
}
}

public class Demonstration_112 {


public static void main(String args[]) {
ThreadX x = new ThreadX();
Thread t1 = new Thread(x);

ThreadY y = new ThreadY();


Thread t2 = new Thread(y);

//ThreadZ z = new ThreadZ();


//Thread t3 = new Thread(z);
Thread t3 = new Thread(new ThreadZ());

t1.start();
t2.start();
t3.start();

System.out.println("... Multithreading is over ");


}
}

OUTPUT:
Thread X with i = -1
Thread X with i = -2
Thread Z with k = 1
Thread Z with k = 3
Thread Z with k = 5
Thread Z with k = 7
Thread Z with k = 9
Exiting Thread Z ...
... Multithreading is over
Thread Y with j = 2
Thread Y with j = 4
Thread Y with j = 6
Thread Y with j = 8
Thread Y with j = 10
Exiting Thread Y ...
Thread X with i = -3
Thread X with i = -4
Thread X with i = -5
Exiting Thread X ...

Note : Note in the above example, how after implementing objects, their thread is created and
their threads start execution. Also note that, a class instance with the run( ) method defined
within must be passed in as an argument in creating the thread instance so that when the start()
method of this Thread instance is called, Java run time knows which run() method to execute.
This alternative method of creating a thread is useful when the class defining run() method needs
to be a sub class of other classes; the class can inherit all the data and methods of the super
class.

Life cycle of threads


Each thread is always in one of five states, which is depicted in Figure 6.1
Figure 6.1 : Five states of a thread
Newborn : When a thread is created (by new statement ) but not yet to run, it is called in
Newborn state. In this state, the local data members are allocated and initialized.
Runnable : The Runnable state means that a thread is ready to run and is awaiting for the
control of the processor, or in other words, threads are in this state in a queue and wait their
turns to be executed.
Running : Running means that the thread has control of the processor, its code is currently
being executed and thread will continue in this state until it get preempted by a higher priority
thread, or until it relinquishes control.
Blocked : A thread is Blocked means that it is being prevented from the Runnable ( or Running)
state and is waiting for some event in order for it to reenter the scheduling queue.
Dead : A thread is Dead when it finishes its execution or is stopped (killed) by another thread.
Threads move from one state to another via a variety of means. The common methods for
controlling a thread's state is shown in Figure 6.1. Below, we are to summarize these methods :
start ( ) : A newborn thread with this method enter into Runnable state and Java run time create
a system thread context and starts it running. This method for a thread object can be called once
only
stop( ) : This method causes a thread to stop immediately. This is often an abrupt way to end a
thread.
suspend( ) : This method is different from stop( ) method. It takes the thread and causes it to
stop running and later on can be restored by calling it again.
resume ( ) : This method is used to revive a suspended thread. There is no gurantee that the
thread will start running right way, since there might be a higher priority thread running already,
but, resume()causes the thread to become eligible for running.
sleep (int n ) : This method causes the run time to put the current thread to sleep for n
milliseconds. After n milliseconds have expired, this thread will become elligible to run again.
yield( ) : The yield() method causes the run time to switch the context from the current thread to
the next available runnable thread. This is one way to ensure that the threads at lower priority do
not get started.
Other methods like wait(), notify(), join() etc. will be discussed in subsequent discussion. Let us
illustrate the use of these method in a simple Application.

Illustration 6.3

/* Demonstration of thread class methods : getID() */


/* Java code for thread creation by extending the Thread class */
class ThreadId extends Thread {
public void run() {
try {
// Displaying the thread that is running
System.out.println ("Thread " + Thread.currentThread().getId() + " is
running");
}
catch (Exception e) {
// Throwing an exception
System.out.println ("Exception is caught");
}
}
}

public class Demonstration_113{


public static void main(String[] args)
{
int n = 8; // Number of threads
for (int i=0; i<8; i++)
{
ThreadId object = new ThreadId();
object.start();
}
}
}

OUTPUT:
Thread 21 is running
Thread 22 is running
Thread 23 is running
Thread 25 is running
Thread 26 is running
Thread 27 is running
Thread 24 is running
Thread 28 is running

Illustration 6.4

/* Demonstration of thread class methods : getID() */


/* Java code for thread creation by implementing the Runnable Interface */

class ThreadId implements Runnable


{
public void run() {
try {
// Displaying the thread that is running
System.out.println ("Thread " + Thread.currentThread().getId() + " is
running");
}
catch (Exception e)
{
// Throwing an exception
System.out.println ("Exception is caught");
}
}
}

// Main Class
class Demonstration_114 {
public static void main(String[] args)
{
int n = 8; // Number of threads
for (int i=0; i<8; i++){
Thread object = new Thread(new ThreadId());
object.start();
}
}
}
OUTPUT:
Thread 21 is running
Thread 23 is running
Thread 24 is running
Thread 25 is running
Thread 22 is running
Thread 27 is running
Thread 26 is running
Thread 28 is running

Illustration 6.5

/* Use of yield(), stop() and sleep() methods */

class ClassA extends Thread{


public void run() {
System.out.println("Start Thread A ....");
for(int i = 1; i <= 5; i++) {
if (i==1) yield();
System.out.println("From Thread A: i = "+ i);
}
System.out.println("... Exit Thread A");
}
}

class ClassB extends Thread{


public void run() {
System.out.println("Start Thread B ....");
for(int j = 1; j <= 5; j++) {
System.out.println("From Thread B: j = "+ j);
if (j==2) stop();
}
System.out.println("... Exit Thread B");
}
}

class ClassC extends Thread{


public void run() {
System.out.println("Start Thread C ....");
for(int k = 1; k <= 5; k++) {
System.out.println("From Thread B: j = "+ k);
if (k==3){
try{
sleep(1000);
}catch(Exception e){}
}
}
System.out.println("... Exit Thread C");
}
}

public class Demonstration_115{


public static void main (String args[]) {
ClassA t1 = new ClassA();
ClassB t2 = new ClassB();
ClassC t3 = new ClassC();
t1.start(); t2.start(); t3.start();
System.out.println("... End of executuion ");
}
}

OUTPUT:
Start Thread A ....
Start Thread C ....
Start Thread B ....
... End of executuion
From Thread A: i = 1
From Thread B: j = 1
From Thread B: j = 2
From Thread B: j = 1
From Thread A: i = 2
From Thread A: i = 3
From Thread A: i = 4
From Thread A: i = 5
... Exit Thread A
From Thread B: j = 2
From Thread B: j = 3
From Thread B: j = 4
From Thread B: j = 5
... Exit Thread C

Illustration 6.6

/* Use of suspend() and resume() methods */

class Thread1 extends Thread {


public void run( ) {
try{
System.out.println (" First thread starts running" );
sleep(10000);
System.out.println (" First thread finishes running" );
}
catch(Exception e){ }
}
}

class Thread2 extends Thread {


public void run( ) {
try{
System.out.println ( "Second thread starts running");
System.out.println ( "Second thread is suspended itself "
);
suspend( );
System.out.println (" Second thread runs again" );
}
catch(Exception e){ }
}
}

class Demonstration_116{
public static void main (String args[ ] ){
try{
Thread1 first = new Thread1( ); // It is a newborn threa
d i.e. in Newborn state
Thread2 second= new Thread2( ); // another new born thre
ad

first.start( ); // first is scheduled for running


second.start( ); // second is scheduled for running

System.out.println("Revive the second thread" ); // If i


t is suspended
second.resume( );

System.out.println ("Second thread went for 10 seconds sl


eep " );
second.sleep (10000);

System.out.println ("Wake up second thread and finishes r


unning" );
System.out.println ( " Demonstration is finished ");
}
catch(Exception e){ }
}
}
OUTPUT:
Revive the second thread
First thread starts running
Second thread starts running
Second thread is suspended itself
Second thread went for 10 seconds sleep

Status of a Thread
It is some time essential to know some information about threads. There are number of methods
defined in Thread which can be called for getting information about threads. Some of the most
commonly used methods for thread's status are listed here :
currentThread( ) : The CurrentThread() is a static method returns the Thread object which is the
currently running thread.
setName( String s) : The SetName() method is to assign a name s for a thread prior its
execution. This, therefore, identifies the thread with a string name. This is helpful for debugging
multi-threaded programs.
getName( ) : This method returns the current string value of the thread's name as set by
SetName().
setPriority (int p) : This method sets the thread's priotity to an integer value p passed in. There
are several predefined priotiry constants defined in class Thread : MIN-PRIORITY, NORM-
PRIORTY and MAX-PRIORITY, which are 1, 5, and 10 respectively.
getPriority ( ) : This method returns the thread's current priority, a value between 1 and 10.
isAlive ( ) : This method returns true if the thread is started but not dead yet.
isDaemon ( ) : This method returns true if the thread is a daemon thread.
Following is the Illustration 6.7 to give an idea how the above mentioned method may be
utilized.

Illustration 6.7 // Status information of threads //


/* Setting priority to threads */

class ClassA extends Thread{


public void run() {
System.out.println("Start Thread A ....");
for(int i = 1; i <= 5; i++) {
System.out.println("From Thread A: i = "+ i);
}
System.out.println("... Exit Thread A");
}
}
class ClassB extends Thread{
public void run() {
System.out.println("Start Thread B ....");
for(int j = 1; j <= 5; j++) {
System.out.println("From Thread B: j = "+ j);
}
System.out.println("... Exit Thread B");
}
}

class ClassC extends Thread{


public void run() {
System.out.println("Start Thread C ....");
for(int k = 1; k <= 5; k++) {
System.out.println("From Thread B: j = "+ k);
}
System.out.println("... Exit Thread C");
}
}

class Demonstration_117{
public static void main (String args[]) {
ThreadA t1 = new ThreadA();
ThreadB t2 = new ThreadB();
ThreadC t3 = new ThreadC();

t3.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(t2.getPriority() + 1);
t1.setPriority(Thread.MIN_PRIORITY);

t1.start(); t2.start(); t3.start();


System.out.println("... End of executuion ");
}
}
OUTPUT:
Start Thread A ....
From Thread A: i = 1
From Thread A: i = 2
From Thread A: i = 3
From Thread A: i = 4
From Thread A: i = 5
... Exit Thread A
... End of executuion
Start Thread B ....
Start Thread C ....
From Thread B: j = 1
From Thread B: j = 2
From Thread B: j = 3
From Thread B: j = 4
From Thread B: j = 5
... Exit Thread B
From Thread B: j = 1
From Thread B: j = 2
From Thread B: j = 3
From Thread B: j = 4
From Thread B: j = 5
... Exit Thread C

Illustration 6.8
/* Data race example. */

public class Demonstration_118 extends Thread {


public static int x;
public void run() {
for (int i = 0; i < 100; i++) {
x = x + 1;
x = x - 1;
}
}
public static void main(String[] args) {
x = 0;
for (int i = 0; i < 1000; i++){
new Demonstration_118().start();
System.out.println(x); // x not always 0!
}
}
}

Synchronization and Inter-Thread Communication


It is already mentioned that threads in Java are running in the same memory space, and hence it
is easy to communicate between two threads. Inter-thread communications allow threads to talk
to or wait on each other. Again, because all the threads in a program share the same memory
space, it is possible for two threads to access the same variables and methods in object.
Problems may occur when two or more threads are accessing the same data concurrently, for
example, one thread stores data into the shared object and the other threads reads data, there
can be synchronization problem if the first thread has not finished storing the data before the
second one goes to read it. So we need to take care to access the data by only one thread
process at a time. Java provides unique language level support for such synchronization. in this
Section we will learn how synchronization mechanism and inter-thread communications are
possible in Java.

Synchronization
To solve the critical section problem, one usual concept is known what is called monitor. A
monitor is an object which is used as a mutually exclusive lock ( called mutex). Only one thread
may 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
owner thread exits the monitor. But in Java, there is no such monitor. In fact, all Java object have
their own implicit monitor associated with them. Here, the key word synchronized is used by
which method (s) or block of statements can be made protected from the simultaneous access.
With this, when a class is designed with threads in mind, the class designer decides which
methods should not be allowed to execute concurrently. when a class with synchronized method
is instantiated, the new object is given its own implicit monitor. The entire time that a thread is
inside of a synchronized method, all other threads that try to call any other synchronized method
on the same instance have to wait. In order to exit the monitor and relinquish control of the object
to the next waiting thread the monitor owner simply needs to return from the method.
Let us illustrate this mechanism with a simple example.
Suppose, we want to maintain a bank account of customers. Several transactions, such as
deposite some amount to an account and withdraw some amount from an account etc. are
possible. Now, for a given account, if two or more transactions come simultaneously then only
one transaction should be allowed at a time instead of simulataneous transaction processing so
that data inconsistency will never occur. So, what we need is to synchronize the
transaction. Illustration 6.9 is to implement such a task.

Illustration 6.9
/* The following Java application shows how the transactions in a bank can be carr
ied out concurrently. */
class Account {
public int balance;
public int accountNo;
void displayBalance() {
System.out.println("Account No:" + accountNo + "Balance: " + bala
nce);
}

synchronized void deposit(int amount){


balance = balance + amount;
System.out.println( amount + " is deposited");
displayBalance();
}

synchronized void withdraw(int amount){


balance = balance - amount;
System.out.println( amount + " is withdrawn");
displayBalance();
}
}

class TransactionDeposit implements Runnable{


int amount;
Account accountX;
TransactionDeposit(Account x, int amount){
accountX = x;
this.amount = amount;
new Thread(this).start();
}
public void run(){
accountX.deposit(amount);
}
}

class TransactionWithdraw implements Runnable{


int amount;
Account accountY;

TransactionWithdraw(Account y, int amount) {


accountY = y;
this.amount = amount;
new Thread(this).start();
}

public void run(){


accountY.withdraw(amount);
}
}

class Demonstration_119{
public static void main(String args[]) {
Account ABC = new Account();
ABC.balance = 1000;
ABC.accountNo = 111;
TransactionDeposit t1;
TransactionWithdraw t2;
t1 = new TransactionDeposit(ABC, 500);
t2 = new TransactionWithdraw(ABC,900);
}
}

OUTPUT:
500 is deposited
Account No:111Balance: 1500
900 is withdrawn
Account No:111Balance: 600

In the above example, the keyword synchronized is used for the methods void deposite(..) and
void withdraw(�) so that these two methods will never run for the same object instance
simultaneously.
Alternatively, if one wants to design a class that was not designed for multi-thread access and
thus has non-synchronized methods, then it can be wrapped the call to the methods in a
synchronized block. Here is the general form of the synchronized statement :

synchronized (Object ) { block of statement(s) }


where Object is any object reference. For example, make all the methods in Account class as
non-synchronized (remove the synchronized key word). Then modify the code for run( ) in class
TransactionDeposite and class TransactionWithdraw are as under :
public void run( ) { // in TransactionDeposite
synchronized (accountX ) {
accountX.deposite(amount );
}
}

public void run( ) { // in TransactionWithdraw


synchronized (accountY ) {
accountY.withdraw(amount );
}
}

You will get the same output.


Interested reader may try to run the program without using synchronization and observe the
result.
Note : In a class, non-synchronized methods are concurrently executable.

Inter-thread Communication
There are three ways for threads to communicate with each other. The first is through commonly
shared data. All the threads in the same program share the same memory space. If an object is
accessible to various threads then these threads share access to that object's data member and
thus communicate each other.
The second way for threads to communicate is by using thread control methods. There are such
three methods by which threads communicate for each other :
suspend ( ): A thread can suspend itself and wait till other thread resume it.
resume ( ): A thread can wake up other waiting thread (which is waiting using suspend() )
through its resume() method and then can run concurrently.
join ( ) :This method can be used for the caller thread to wait for the completion of called thread.
The third way for threads to communicate is the use of three methods; wait(), notify(), and
notifyAll(); these are defined in class Object of package java.lang. Actually these three methods
provide an elegant inter-process communication mechanism to take care the deadlock situation
in Java. As there is multi-threading in program, deadlock may occur when a thread holding the
key to monitor is suspended or waiting for another thread's completion. If the other thread is
waiting for needs to get into the same monitor, both threads will be waiting for ever. The uses of
these three methods are briefed as below :
wait ( ):This method tells the calling thread to give up the monitor and make the calling thread
wait until either a time out occurs or another thread call the same thread's notify() or notifyAll()
method.
Notify ( ): This method wakes up the only one (first) waiting thread called wait() on the same
object.
notifyAll( ): This method will wake up all the threads that have been called wait( ) on the same
object.
Now, let us demonstrate the classical use of these methods. Illustration 6.6 is for this purpose.

Illustration 6.10 : // Inter thread communication : Producer & Consu


mer problem //

class Q { // Q is a class containing two parallel


processes
int n;
boolean flag = false;
//PRODUCER
synchronized void put( int n) { // Produce a value
if(flag) {
// Entry
try wait( ); catch(InterruptedException e);
// to the
}
// critical section

this.n = n;

System.out.println( "Produce :" + n);


// Critical Section
flag = true;
// Exit from the
notify( );
// critical section
}
//CONSUMER
synchronized int get( ) { // Consume a value
if(! flag) {
// Entry
try wait( ); catch(InterruptedException e);
// to the
}
// critical section

System.out.println( "Consume :" + n);


// Critical Section

flag = false;
// Exit from the
notify( );
// critical // section
return( n );

class Producer implement Runnable { // Thread for Producer process


Q q;
Producer ( Q q ) { // constructor
this.q =q;
new thread (this).start ( ) ; // Producer process is
started
}

public void run( ) { // infinite running thread for Producer


int i = 0;
while (true )
q.put ( i++ );
}
}

class Consumer implement Runnable { // Thread for consumer process


Q q;
Consumer (Q q ) { // Constructor
this.q = q;
new Thread (this).start ( );
}

public void run( ) { // infinite running thread for Consumer


while (true)
q.get ( );
}
}

class PandC {
public static void main( String args[ ] ) {
Q q = new Q( ); // an instance of parallel processes is
created
new Producer(q) ; // Run the thread for p
roducer
new Consumer (q); // Run consumer thread
}
}

To understand this critical section problem in operating system design, user may be referred to
: Operating system concept by Peterson and Sylberchotze , Addiction Wesley Inc.
Note : All three methods i.e. wait(), notify(), and notifyAll() must only be called from the inside of
synchronized methods.

Thread Groups and Daemon


There are two other variation in thread class known : ThreadGroup and Daemon. ThreadGroup,
as its name implies, is a group of threads. A thread group can have both threads and other
thread groups as its member elements. In Java, there is a default thread group called
SystemThreadGroup, which is nothing but the Java run time itself. When a Java application is
started, the Java run time creates the main thread group as a member of the system thread
group. A main thread is created in the main thread group to run the main( ) method of the
Application. In fact, every thread instance is member of exactly one thread group. By default, all
new user created threads and thread groups) will become the members of the main thread
group. All the threads and thread in an application form a tree with the system thread group as
the root.
Daemon threads are service threads. They exist to provide service threads. They exist to provide
services to other threads. They normally run in an infinite loop and attending the client threads
requesting services. When no other threads exist daemon thread is automatically ceased to
exist.
A new thread group can be created by instantiating the thread group class. For example,

Threadgroup TG = new ThreadGroup ( ) ;


Thread T = new Thread ( TG) ;
These two statements creates a new thread group TG which contains a thread T as the only
member.
To create a daemon thread, there is a method setDaemon() can be called just after the creation
of a thread and before the execution is started. For example, following two statement is to make
a thread as demon thread.

Thread T = new Thread ( ) ;


T setDaemon (true);
The constructor of the thread is a good candidate for making this method call, Also, by default, all
the threads created by a daemon thread are also daemon thread.
Some commonly used methods for handling thread groups and daemon are listed below :

getName ( ) :Returns the name of the thread group .


setName ( ) :Sets the name of the thread group .
geParent ( ) :Returns the parent thread group of the thread group .
getMaxPriority :Returns the current maximum priority of the thread group.
activeCount ( ) :Returns the number of active threads in the thread group.
activeGroupCount :Returns the number of active threads groups in the
thread group.
isDaemon ( ) :Returns true if the thread is a daemon thread.
setDaemon ( ) : Set the thread as a daemon thread prior its starting
execution.

Practice Questions
Practice 6.1
/* Practice of a multithreaded program using subclassing Thread */
class ThreadA extends Thread{
public void run( ) {
for(int i = 1; i <= 5; i++) {
System.out.println("From Thread A with i = "+ -1*i);
}
System.out.println("Exiting from Thread A ...");
}
}

class ThreadB extends Thread{


public void run( ) {
for(int j = 1; j <= 5; j++) {
System.out.println("From Thread B with j = "+ 2*j);
}
System.out.println("Exiting from Thread B ...");
}
}

class ThreadC extends Thread{


public void run( ) {
for(int k = 1; k <= 5; k++) {
System.out.println("From Thread C with k = "+ (2*k-1));
}
System.out.println("Exiting from Thread C ...");
}
}

class MultiThreadClass{
public static void main(String args[]) {
ThreadA a = new ThreadA();
ThreadB b = new ThreadB();
ThreadC c = new ThreadC();

a.start();
b.start();
c.start();

System.out.println("... Multithreading is over ");


}
}
Practice 6.2
/* Practice of a multithreaded program using Runnable interface */
class ThreadX implements Runnable{
public void run( ) {
for(int i = 1; i <= 5; i++) {
System.out.println("Thread X with i = "+ i);
}
System.out.println("Exiting Thread X ...");
}
}

class ThreadY implements Runnable{


public void run( ) {
for(int j = 1; j <= 5; j++) {
System.out.println("Thread Y with j = "+ j);
}
System.out.println("Exiting Thread Y ...");
}
}

class ThreadZ implements Runnable{


public void run( ) {
for(int k = 1; k <= 5; k++) {
System.out.println("Thread Z with k = "+ k);
}
System.out.println("Exiting Thread Z ...");
}
}

class MultiThreadRunnable{
public static void main(String args[]) {
ThreadX x = new ThreadZ(); Thread t1 = new Thread(x);
ThreadY y = new ThreadY(); Thread t2 = new Thread(y);
ThreadZ z = new ThreadZ(); Thread t3 = new Thread(z);
t1.start();
t2.start();
t3.start();
System.out.println("... Multithreading is over ");
}
}

Practice 6.3
/* Use of yield(), stop() and sleep() methods */

class ClassA extends Thread{

public void run() {

System.out.println("Start Thread A ....");

for(int i = 1; i <= 5; i++) {

if (i==1) yield();

System.out.println("From Thread A: i = "+ i);

System.out.println("... Exit Thread A");

class ClassB extends Thread{

public void run() {

System.out.println("Start Thread B ....");

for(int j = 1; j <= 5; j++) {

System.out.println("From Thread B: j = "+ j);


if (j==2) stop();

System.out.println("... Exit Thread B");

class ClassC extends Thread{

public void run() {

System.out.println("Start Thread C ....");

for(int k = 1; k <= 5; k++) {

System.out.println("From Thread B: j = "+ k);

if (k==3){

try{

sleep(1000);

}catch(Exception e){}

System.out.println("... Exit Thread C");


}

class ThreadControl{

public static void main (String args[]) {

ThreadA t1 = new ThreadA();

ThreadB t2 = new ThreadB();

ThreadC t3 = new ThreadC();

t1.start(); t2.start(); t3.start();

System.out.println("... End of executuion ");

Practice 6.4
/* Use of suspend() and resume() methods */
class Thread1 extends Thread {
public void run( ) {
System.out.println (" First thread starts running" );
sleep(10000);
System.out.println (" First thread finishes running" );
}
}
class Thread2 extends Thread {
public void run( ) {
System.out.println ( "Second thread starts running");
System.out.println ( "Second thread is suspended itself ");
suspend( );
System.out.println (" Second thread runs again" ));
}
}

class AnotherThreadControl {
public static void main (String, args[ ] ) {
Thread1 fist = new Thread1( ); // It is a newborn thread i.e. in
Newborn state
Thread2 second= new Thread2( ); // another new born thread
first.start( ); // first is scheduled for running
second.start( ); // second is scheduled for running

System.out.println("Revive the second thread" ); // If it is sus


pended
second.resume( );
System.out.println ("Second thread went for 10 seconds sleep " );
Second.sleep (10000);
System.out.println ("Wake up second thread and finishes running"
);
System.out.println ( " Demonstration is finished ");
}
}
Practice 6.5
/* Setting priority to threads */
class ClassA extends Thread{
public void run() {
System.out.println("Start Thread A ....");
for(int i = 1; i <= 5; i++) {
System.out.println("From Thread A: i = "+ i);
}
System.out.println("... Exit Thread A");
}
}

class ClassB extends Thread{


public void run() {
System.out.println("Start Thread B ....");
for(int j = 1; j <= 5; j++) {
System.out.println("From Thread B: j = "+ j);
}
System.out.println("... Exit Thread B");
}
}

class ClassC extends Thread{


public void run() {
System.out.println("Start Thread C ....");
for(int k = 1; k <= 5; k++) {
System.out.println("From Thread B: j = "+ j);
}
System.out.println("... Exit Thread C");
}
}

class ThreadPriorityTest{
public static void main (String args[]) {
TheadA t1 = new ThreadA();
TheadB t2 = new ThreadB();
TheadC t3 = new Thread3();

t3.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.getPriority() + 1);
t1.setPriority(Thread.MIN_PRIORITY);
t1.start(); t2.start(); t3.start();
System.out.println("... End of executuion ");
}
}
Practice 6.6
/* Following Java application create a list of numbers and then sort in ascending
order as well as in descending order simultaneously. */
import java.util.*;

class Numbers {
public int result[] = new int[10];
void displayListOfNos()
{
System.out.println("Numbers stored in the array:");
for( int idx=0; idx<10; ++idx) {
System.out.println(result[idx]);
}
}

void fillTheArray(int aUpperLimit, int aArraySize)


{
if (aUpperLimit <=0) {
throw new IllegalArgumentException("UpperLimit must be positive: " + aUpp
erLimit);
}

if (aArraySize <=0) {
throw new IllegalArgumentException("Size of returned List must be greater
than 0.");
}

Random generator = new Random();


for( int idx=0; idx<="" result[j])="" int="" temp="result[i];" result[i]=
"result[j];" result[j]="temp;" sortdescending()="" style="box-sizing: border-box;"
> result[j]) {
int temp = result[i];
result[i] = result[j];
result[j] = temp;
}
}
}

displayListOfNos();
}
}
class ArrangementAscending implements Runnable {
Numbers n1 ;
ArrangementAscending(Numbers n) {
n1 = n;
new Thread(this).start();
}
public void run() {
n1.sortAscending();
}
}

class ArrangementDescending implements Runnable {


Numbers n2;
ArrangementDescending(Numbers n) {
n2 = n;
new Thread(this).start();
}

public void run() {


n2.sortDescending();
}
}

class ArrangingNos {

public static void main(String args[]) {


Numbers n = new Numbers();
n.fillTheArray(20,10);
ArrangementAscending a1 = new ArrangementAscending(n);
ArrangementDescending d1 = new ArrangementDescending(n);
}
}

Practice 6.7
/* The following Java application shows how the transactions in a bank can be carr
ied out concurrently. */
class Account {
public int balance;
public int accountNo;
void displayBalance()
{
System.out.println("Account No:" + accountNo + "Balance: " + balance);
}

synchronized void deposit(int amount)


{
balance = balance + amount;
System.out.println( amount + " is deposited");
displayBalance();
}

synchronized void withdraw(int amount)


{
balance = balance - amount;
System.out.println( amount + " is withdrawn");
displayBalance();
}
}

class TransactionDeposit implements Runnable


{
int amount;
Account accountX;
TransactionDeposit(Account x, int amount)
{
accountX = x;
this.amount = amount;
new Thread(this).start();
}

public void run()


{
accountX.deposit(amount);
}
}

class TransactionWithdraw implements Runnable


{
int amount;
Account accountY;
TransactionWithdraw(Account y, int amount) {
accountY = y;
this.amount = amount;
new Thread(this).start();
}
public void run()
{
accountY.withdraw(amount);
}
}

class Transaction {
public static void main(String args[]) {
Account ABC = new Account();
ABC.balance = 1000;
ABC.accountNo = 111;
TransactionDeposit t1;
TransactionWithdraw t2;
t1 = new TransactionDeposit(ABC, 500);
t2 = new TransactionWithdraw(ABC,900);
}
}

Assignment
Q: Write a Java program which handles Push operation and Pop operation
on stack concurrently.
Q: Write a Java program which first generates a set of random numbers and
then determines negative, positive even, positive odd numbers
concurrently.

Q&A
QWhat is the thread?
:
AA thread is a lightweight subprocess. It is a separate path of execution because
: each thread runs in a different stack frame. A process may contain multiple
threads. Threads share the process resources, but still, they execute
independently..
QHow to implement Threads in java?
:
AThreads can be created in two ways i.e. by implementing java.lang.Runnable
: interface or extending java.lang.Thread class and then extending run method.
Thread has its own variables and methods, it lives and dies on the heap. But a
thread of execution is an individual process that has its own call stack. Thread are
lightweight process in java.
1)Thread creation by implementingjava.lang.Runnableinterface. We will create
object of class which implements Runnable interface :
MyRunnable runnable=new MyRunnable();

Thread thread=new Thread(runnable);

2) And then create Thread object by calling constructor and passing reference of
Runnable interface i.e. runnable object :
Thread thread=new Thread(runnable);

QDoes Thread implements their own Stack, if yes how?


:
AYes, Threads have their own stack. This is very interesting question, where
: interviewer tends to check your basic knowledge about how threads internally
maintains their own stacks.Shown in figure below.
QWhat is multithreading?
:
AMultithreading is a process of executing multiple threads simultaneously.
: Multithreading is used to obtain the multitasking. It consumes less memory and
gives the fast and efficient performance. Its main advantages are:

• Threads share the same address space.


• The thread is lightweight.
• The cost of communication between the processes is low.

QWhat do you understand by inter-thread communication?


:
A• The process of communication between synchronized threads is termed as inter-
: thread communication.
• Inter-thread communication is used to avoid thread polling in Java.
• The 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 can be obtained by wait(), notify(), and notifyAll() methods.
QHow can you say Thread behaviour is unpredictable?
:
AThread behaviour is unpredictable because execution of Threads depends on
: Thread scheduler, thread scheduler may have different implementation on different
platforms like windows, unix etc. Same threading program may produce different
output in subsequent executions even on same platform. To achieve we are going
to create 2 threads on same Runnable Object, create for loop in run() method and
start both threads. There is no surety that which threads will complete first, both
threads will enter anonymously in for loop.
QHow can you ensure all threads that started from main must end in order in
: which they started and also main should end in last?
AWe can use join() methodto ensure all threads that started from main must end in
: order in which they started and also main should end in last.In other words waits for
this thread to die. Calling join() method internally calls join(0).
QWhat is difference between starting thread with run() and start() method?
:
AWhen you call start() method, main thread internally calls run() method to start
: newly created Thread, so run() method is ultimately called by newly created thread.
When you call run() method main thread rather than starting run() method with
newly thread it start run() method by itself.
QWhat is significance of using Volatile keyword?
:
AJava allows threads to access shared variables. As a rule, to ensure that shared
: variables are consistently updated, a thread should ensure that it has exclusive use
of such variables by obtaining a lock that enforces mutual exclusion for those
shared variables.
If a field is declared volatile, in that case the Java memory model ensures that all
threads see a consistent value for the variable.
Note:volatile is only a keyword, can be used only with variables.
QWhat is race condition in multithreading and how can we solve it?
:
AWhen more than one thread try to access same resource without synchronization
: causes race condition.
So we can solve race condition by using either synchronized block or synchronized
method. When no two threads can access same resource at a time phenomenon is
also called as mutual exclusion.
QWhen should we interrupt a thread?
:
AWe should interrupt a thread when we want to break out the sleep or wait state of a
: thread. We can interrupt a thread by calling the interrupt() throwing the
InterruptedException.
QWhat is the purpose of the Synchronized block?
:
AThe Synchronized block can be used to perform synchronization on any specific
: resource of the method. Only one thread at a time can execute on a particular
resource, and all other threads which attempt to enter the synchronized block are
blocked.
• Synchronized block is used to lock an object for any shared resource.
• The scope of the synchronized block is limited to the block on which, it is
applied. Its scope is smaller than a method.

QWhat is the difference between notify() and notifyAll()?


:
AThe notify() is used to unblock one waiting thread whereas notifyAll() method is
: used to unblock all the threads in waiting state.
QHow to detect a deadlock condition? How can it be avoided?
:
AWe can detect the deadlock condition by running the code on cmd and collecting
: the Thread Dump, and if any deadlock is present in the code, then a message will
appear on cmd. Ways to avoid the deadlock condition in Java:

• Avoid Nested lock: Nested lock is the common reason for deadlock as
deadlock occurs when we provide locks to various threads so we should
give one lock to only one thread at some particular time.
• Avoid unnecessary locks: we must avoid the locks which are not required.
• Using thread join: Thread join helps to wait for a thread until another thread
doesn't finish its execution so we can avoid deadlock by maximum use of
join method.

QDifference between wait() and sleep().


:
Acalled from synchronized block :wait() method is always called from
: synchronized block i.e. wait() method needs to lock object monitor before object on
which it is called. But sleep() method can be called from outside synchronized block
i.e. sleep() method doesn�t need any object monitor.
IllegalMonitorStateException : if wait() method is called without acquiring object
lock than IllegalMonitorStateException is thrown at runtime, but sleep()
methodnever throws such exception.
Belongs to which class: wait() method belongs to java.lang.Object class but
sleep() method belongs to java.lang.Thread class.
Called on object or thread: wait() method is called on objects but sleep() method
is called on Threads not objects.
Thread state: when wait() method is called on object, thread that holded object�s
monitor goes from running to waiting state and can return to runnable state only
when notify() or notifyAll()method is called on that object. And later thread
scheduler schedules that thread to go from from runnable to running state.
when sleep() is called on thread it goes from running to waiting state and can return
to runnable state when sleep time is up.
When called from synchronized block:when wait() method is called thread
leaves the object lock. But sleep()method when called from synchronized block or
method thread doesn�t leaves object lock.
QSimilarity between yield() and sleep().
:
A • yield() and sleep() method belongs to java.lang.Thread class.
: • yield() and sleep() method can be called from outside synchronized block.
• yield() and sleep() method are called on Threads not objects.

QWhat are daemon threads?


:
ADaemon threads are low priority threads which runs intermittently in background for
: doing garbage collection.
Few salient features of daemon() threads>

• Thread scheduler schedules these threads only when CPU is idle.


• Daemon threads are service oriented threads, they serves all other threads.
• These threads are created before user threads are created and die after all
other user threads dies.
• Priority of daemon threads is always 1 (i.e. MIN_PRIORITY).
• User created threads are non daemon threads.
• JVM can exit when only daemon threads exist in system.
• we can use isDaemon() method to check whether thread is daemon thread
or not.
• we can use setDaemon(boolean on) method to make any user method a
daemon thread.
• If setDaemon(boolean on) is called on thread after calling start() method
than IllegalThreadStateException is thrown.

QCan a constructor be synchronized?


:
ANo, constructor cannot be synchronized. Because constructor is used for
: instantiating object, when we are in constructor object is under creation. So, until
object is not instantiated it does not need any synchronization.

• Enclosing constructor in synchronized block will generate compilation error.

• Using synchronized in constructor definition will also show compilation error.


COMPILATION ERROR = Illegal modifier for the constructor in type
ConstructorSynchronizeTest; only public, protected & private are permitted
we can use synchronized block inside constructor.

You might also like