Java Notes 5
Java Notes 5
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 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 ...");
}
}
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
:
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 ...");
}
}
t1.start();
t2.start();
t3.start();
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.
Illustration 6.3
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
// 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
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
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
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.
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);
Illustration 6.8
/* Data race example. */
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);
}
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 :
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.
this.n = n;
flag = false;
// Exit from the
notify( );
// critical // section
return( n );
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.
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 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();
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 */
if (i==1) yield();
if (k==3){
try{
sleep(1000);
}catch(Exception e){}
class ThreadControl{
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
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]);
}
}
if (aArraySize <=0) {
throw new IllegalArgumentException("Size of returned List must be greater
than 0.");
}
displayListOfNos();
}
}
class ArrangementAscending implements Runnable {
Numbers n1 ;
ArrangementAscending(Numbers n) {
n1 = n;
new Thread(this).start();
}
public void run() {
n1.sortAscending();
}
}
class ArrangingNos {
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);
}
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();
2) And then create Thread object by calling constructor and passing reference of
Runnable interface i.e. runnable object :
Thread thread=new Thread(runnable);
• 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.