You are on page 1of 35

Multithreading – Concepts::

Introduction

Comparative to other languages, multithreading is very easy and simple in


Java and the credit goes to the portability nature and support of many
Java API classes. The built-in support for threads is simple and straight
so that any programmer can do with multithreading operations without
confusion and special attention. Multithreading uses very effectively the
microprocessor time by reducing its idle time. When the processor's idle
time is reduced, the output of the programs comes earlier. Multithreading
is a concept that should be supported by the operating system. Now-a-
days, all operating systems support multithreading.

Multitasking, Multiprocessing and Multithreading

A program under execution is called a process. The general definition, a


novice expresses, of multithreading is "performing multiple tasks at the
same time is called multitasking ". This is very wrong and is the result
of misunderstanding the concept. Every computer person knows well that
microprocessor can execute only one instruction (task) at a time. That
is, the earlier definition is going wrong somewhere else. This is the
point of confusion about multithreading for everyone. Let us be clear
about the concept. When a process is being executed, there may be an
interruption, sometimes, for execution; for example, a keyboard input
(scanf) may not be fed immediately. When not fed, the execution is halted
(observe, the cursor will be blinking even for the whole day when the
input is not given). Now the processor is free and idle. We can ask the
microprocessor to do another process meantime. The processor obliges (as
underlying OS supports multitasking). Now, two programs are under
execution – the first one half the way completed and kept apart and the
other being executed. When the second task (process) is over, if the
input is ready, the control will be shifted to the first process and now
the first process is executed completely. The result is output of both
the programs is obtained earlier. All this is transparent (not known) to
the user as context switching occurs at very fast speed.

"Shifting the microprocessor to execute another process when the first


process is stopped its execution, is known as multitasking". Shifting
between the processes is known as context switching. Do not shift
unnecessarily when the first program is going smooth with its execution
as context switching takes more time and performance looses. Shift only
when a running process is stopped for some reason.

Putting multiple processors (say two) and feeding multiple processes


simultaneously is known as multiprocessing and is a very rare phenomenon
as multiple processors on desktop PCs is uncommon (only super computers
have).

Multithreading is the Java's style of achieving multitasking. A single


Java program can be divided into a number of threads and executed
simultaneously while shifting between the threads when one stops its
execution. The current tutorial discusses how to divide a Java program
into multiple threads and how to execute them.

Simultaneously, concurrently, parallely

These terms are put here as they are again confusing. All means the same
of doing multiple tasks at the same time. "At the same time" is a
confusing idiom. Many processes may exist whose execution is stopped in
the middle for some reason. Remember, only one can be active at any time.
Which ever process is ready is called and executed. "Many" must be
interpreted this way. It looks all at a time as context switching happens
very fast (like cinema where a number of frames of images are run is such
a speed, our eye cannot catch). Some more confusing terms are Preemptive
and Cooperative Multitasking and Time-sharing . These terms are also
discussed hereunder.

Preemptive multitasking and Time-sharing

At a given time, a number of processes may be getting executed on the


CPU. CPU allocates a certain period of time, known as time-slice, for
each process to execute. Each process is guaranteed of a time-slice. In
preemptive multitasking , one process empties (forcibly evacuating) the
other process for the time-slice period and thus every process definitely
gets the CPU time. Thus, CPU time is shared by all the processes and is
known as time sharing. Time sharing is a CPU architecture where CPU
distributes its time equally to all the processes waiting for execution.

Preemptive and Cooperative Multitasking

In multitasking two types of algorithms exists – preemptive multitasking


and cooperative multitasking. In preemptive multitasking, each process is
allotted a certain period of time known as time slice. With time slices,
the waiting processes get evenly all the CPU time and one process cannot
hold the CPU time as long it wants. In contrary, in cooperative
multitasking, one process can hold the microprocessor time as long as it
would like. But the CPU is empowered to remove the process if the process
does not utilize the time after holding it. Preemptive multitasking is
supported by OS/2, UNIX, Windows NT etc. Cooperative multitasking is
supported by Windows 3.1, UNIX, Windows NT etc.

Each type comes with its own advantages. When an immediate action or
attention is required, like keyboard input or a button click, preemptive
is preferred. The disadvantage of cooperative multitasking is, if
designed poorly, it may hang the system.

Preemptive Scheduling and Non-preemptive Scheduling

For forcing the thread to vacate the microprocessor, two properties can
be considered – priority and waiting time. In preemptive scheduling, a
thread with more priority vacates the executing thread of low priority.
That is, low-priority thread yields to the high-priority thread. In
contrary, in non-preemptive scheduling, waiting time is considered and
not priority. That is, the high-priority thread cannot relinquish a low-
priority thread having more waiting time.

Memory Protection

With multitasking, the operating system must be built in a robust way.


One ill-behaved process (a process that went out of control) may ruin or
overwrite the other process data. This is a very serious condition. This
is taken care by the OS in its architecture. Every process (or thread
later) comes with its own execution area known as context area. One
process is not allowed to access, by the OS, other process context area.
To some extent, the programmer can also restrict this by issuing
privileges to the processes. By issuing a low-privilege, the process may
be restricted from accessing a particular memory region.
Java Thread Basics:::

Introduction

If only one process exists before the processor and if the process
execution is stopped for some reason, the microprocessor becomes idle
without any work. This type of programming is known as monolithic
programming. In monolithic programming, the whole process consitutes a
single module. To get a better understanding, Lord Buddha statue in
Hussain Sagar in Hyderabad, India is a monolithic statue (single stone
carvation). The minus point of single stone is if some part is to be
replaced in long future, the whole statue is to be replaced. The same is
the problem with monolithic programming also; if a part of the program is
stopped, the whole program comes to standstill. There comes to the rescue
multithreading.

A Java process can be divided into a number of threads (or to say,


modules) and each thread is given the responsibility of executing a block
of statements. That is, a thread is an incharge of a few statements of a
program. If one thread stops its execution, the execution control can be
shifted to another thread. Remember, here all threads belong to the same
process. This is the advantage of threads over monolithic programming.
The ultimate result is microprocessor idle time is reduced. The end
result is output of the program comes earlier.

A thread is a part of a process. A thread lives within a process. No


process, no thread. To understand better, we cannot keep our brain
outside for sometime and place it back; it is because brain is a part of
human body. Similarly, a thread cannot be there without a process.
Infact, a process is divided into a number of threads.

Now let us define a thread; "a thread is a single sequential flow of


control within a process". It is something confusing. Let us be clear. As
said earlier, a thread comprises of a block statements. These statements
are executed one-by-one sequentially. Every thread maintains its own
execution context within a process context area. We can say, a thread is
a sub process. For execution, one thread does not depend on other; every
thread is independent of other. This tutorial gives you how to divide a
process into a number of threads or to say, how to create threads, how to
assign different tasks, priorities and synchronization

Lightweight process and Heavyweight process

If the execution shifts between the threads of the same process, it is


known as lightweight process. If the execution shifts between the threads
of different processes, it is known as heavyweight process.

In the above figure, if the control shifts between the threads t1 and t2
of the same process p1, it is known as lightweight process. If the
control shifts between the threads t1 of process p1 and t1 of process p2,
it is known as heavyweight process. Generally, threads are designed to be
lightweight because heavyweight is a big overhead to the OS.

Advantages of Multithreading
First and foremost advantage is, as you have understood so far,
microprocessor idle time is reduced and consequently output is obtained
faster. When a program is divided into number of threads, each comprising
a few statements, the code becomes simpler, readability increases,
debugging and maintenance becomes easier. Generally, user's input is very
slow in GUI environment. This late user's response is best utilized by
other threads (reduces overall execution time).

Applications of Multithreading/Multiprocessing

Playing media player while doing some activity on the system like typing
a document.
Transferring data to the printer while typing some file.
Downloading some files like images while browsing is going on
(downloading images is very slow).
Running animation while system is busy on some other work.
Honoring requests from multiple clients by an application/web server.
Threads are useful in handling events generated by components like mouse
etc. A thread is capable to produce a frame with images.
Java API support for Threads

Multithreading is one of the built-in and important feature of Java


language. Java's built-in classes, useful to develop a multithreaded
program, are hereunder and all are from java.lang package.

Class Useful Methods


Thread sleep(), join(), suspend(), resume(), stop() and run() etc.
Runnable interface only run() method
Object wait(), notify() and notifyAll()
ThreadGroup getName(), getParent() and activeCount() etc.
Common Exceptions in Threads

The following are common exceptions that come in thread programming. All
are from java.lang package.

InterruptedException : It is thrown when the waiting or sleeping state is


disrupted by another thread.
IllegalStateException : It is thrown when a thread is tried to start that
is already started.

How to create threads in Java by Extending Thread class?

After knowing what a thread is, it is the time for creating and using the
thread. Java comes with two approaches for creation of thread.

1. By extending Thread class (of java.lang package)


2. By implementing Runnable interface (of java.lang package)

Let us see the first approach.

Aim: To create, start and execute thread by extending Thread class. The
execution should print 0 to 9 numbers with an interval of 1000
milliseconds (1 second).

public class Demo extends Thread


{
public void run()
{
for(int i = 0; i < 10; i++)
{
System.out.println("Iteration: " + i);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Some problem. " + e);
}
}
}
public static void main(String args[])
{
Demo d1 = new Demo();
d1.start();
}
}

How to create threads by implementing Runnable interface?

Once you know thread basics, know how to create threads in Java. Java
comes with two styles of creating threads.

1. Thread creation by extending Thread class


2. Thread creation by implementing Runnable interface

You have seen earlier, the first style and let us go for the second
style.

Aim: To create, start and execute thread by implementing Runnable


interface. The execution should print 0 to 9 numbers with an interval of
1000 milliseconds (1 second).

public class Demo implements Runnable


{
public void run()
{
for(int i = 0; i < 10; i++)
{
System.out.println("Iteration: " + i);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Some problem. " + e);
}
}
}
public static void main(String args[])
{
Demo d1 = new Demo();
Thread t1 = new Thread(d1);
t1.start();
}
}

Create and Start thread with start() in Java Example ::

In Java, a thread can be created in two ways.

a) by extending Thread class


b) by implementing Runnable interface

The following example gives how to create thread and start the thread.
Let us learn through an example.

public class Demo extends Thread


{
public void run()
{
System.out.println("From run() method");
}
public static void main(String args[])
{
Demo d1 = new Demo();
d1.start();
}
}
ima

Demo d1 = new Demo();


d1.start();

In the above code, you say d1 is an object of Demo class. You are right;
but at the same time, d1 is a thread of Demo class. It is so because Demo
class extends Thread class. Observe, it is so simple to create a thread
in Demo class. Just extend the class and create an object. The object
becomes thread automatically.

The thread d1 is created but it is inactive. An inactive thread is not


eligible for microprocessor time. To make the thread active, call start()
method on the thread as d1.start(). start() method is defined in Thread
class.

The start() method implicitly calls run() method. run() method is a


concrete (non-abstract) method of Thread class. That is, calling start()
method calls automatically run() method. This is the job of JVM. run() is
the heart of the thread and any code you would like to be executed by the
thread, write in the run() method.

Do not think of calling d1.run() directly. Thread looses lot of


activities implicitly done by JVM.

Creating and Spawning Threads:::

Threads can be created in two ways in Java.

By extending Thread class.


By implementing Runnable interface.
Why Java requires two types and when to use which type, we will see
later.

1. Creating a thread by extending Thread class

To create a thread, the first style and used generally is by extending


Thread class.

Following is the class signature of Thread class.

public class Thread extends Object implements Runnable


Observe, the Thread class implements Runnable interface.

Read the following program and see how simple to create a thread in Java.
The program prints 0 to 9 numbers with a gap of 1000 milliseconds (1
second); it is the simplest way to create and control the thread.

public class Demo extends Thread


{
public void run()
{
try
{
for( int i = 0; i < 10; i++)
{
System.out.println("Welcome to threads: " + i );
Thread.sleep(1000);
}
}
catch(InterruptedException e)
{
System.err.println("Sleep time is disturbed, you may get
incorrect functionality. " + e);
}

System.out.println("Successful");
}
public static void main(String args[])
{
Demo d1 = new Demo();
d1.start();
}
}

In the above program, Demo class extends Thread. To create a thread in


Java, just extend Thread class and create an object, the object becomes a
thread implicitly. Now, d1 is a thread of Demo class. Actually, d1 is an
object of Demo class but we are calling it as a thread (because Demo
extends Thread). This is how Java makes thread manipulation easy to the
programmer; some more concepts that are made easy, we get later.

Demo d1 = new Demo();


d1.start();
The thread, d1, is created, occupies some memory, but still it is
inactive. An inactive thread is not eligible for microprocessor time even
if the processor is idle. To make the thread active, call start() method
on the thread. Now, d1 becomes active and eligible for a time-slice.
start() is a method of Thread class. Forgetting to call the start()
method makes the thread to die in inactive state itself without
performing the job assigned.

public void run()

Whenever the thread is started, the first and foremost job it does is
calling the run() method. It is a predefined thread of Thread class. This
method is the heart of the thread and whatever code is expected to run by
the thread should be put here. When the execution of run() method is
over, the thread dies implicitly; naturally, its job is over.

Thread.sleep(1000);

sleep() is a method of Thread class inherited from Runnbale interface and


overridden. Following is the method signature.

public static native void sleep(long milliseconds) throws


InterruptedException

It is a static method throwing InterruptedException. Being a checked


exception, whenever the sleep() method is used, the InterruptedException
must be handled, else the code does not compile. The parameter 1000 is of
long data type which indicates the inactive period of time in
milliseconds. By calling sleep() method, the thread is made inactive for
1000 milliseconds (that is, 1 second). When the sleep time is over, the
thread becomes implicitly active and eligible for microprocessor time
(timeout of thread). For every iteration, the thread, d1, becomes
inactive for 1000 milliseconds. sleep() is the easiest way to make the
thread inactive and other ways we see later.

Heavyweight and Lightweight Threads::

We know earlier, the meaning of heavyweight and lightweight threads. Now,


let us see how to create them.

1. Creating Heavyweight Threads

We know earlier, multithreading is nothing but executing multiple threads


simultaneously. In the following program, two threads of different
classes, Test1 and Test2 are created and executed. One thread prints the
numbers in ascending order and the other in descending order,
alternatively. As these threads belong to two different classes, it is an
example of heavyweight process.

class Test1 extends Thread


{
public void run()
{
for(int i = 0; i < 10; i ++)
{
System.out.println("Test1: " + i);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
}
class Test2 extends Thread
{
public void run()
{
for(int i = 9; i >= 0; i--)
{
System.out.println("Test2: " + i);
try
{
Thread.sleep(1000);
}
catch( InterruptedException e )
{
e.printStackTrace();
}
}
}
}
public class TwoRuns
{
public static void main(String args[])
{
Test1 t1 = new Test1();
Test2 t2 = new Test2();
t1.start();
t2.start();
try
{
t1.join();
t2.join();
}
catch( InterruptedException e )
{
e.printStackTrace();
}
}
}
f="http://way2java.com/wp-content/uploads/2011/03/ss.bmp">

The t1 prints 0 and becomes inactive for 1000 milliseconds by calling


sleep() method. As the microprocessor does not have any work (or idle),
it allocates its time to the waiting thread t2. t2 prints 9 and goes for
sleep for 1000 milliseconds. Meantime, t1 comes out of sleep time,
becomes active, prints 1 and again goes for sleep. Then t2 awakes, prints
8 and goes for sleep. Like this, the two loops managed by two threads
(belonging to two different processes), t1 and t2, print the numbers
alternatively. At any time given, only one thread is active and all the
remaining are inactive. You can change the sleep timings and find the
difference in output.
Observe, when t1 is active, t2 is inactive and when t2 is active, t1 is
inactive. sleep() method is the easiest way, a programmer can shift the
execution control from one thread to the other. Other methods also exist,
but to activate an inactive thread, it requires an extra method call;
this we get later.

Note : At different times of execution, you may see t2 starts first even
though t1 is started first. It wholly depends on your processor speed and
time availability.

t1.join();

One thread creates the other. The first thread, implicitly created and
executed at the beginning of the process, is main thread. For us, main()
is a method, but internally it is a thread. Do not get confused, there is
a thread group on the name of main; this we get later. In the above
program, main thread created t1 and t2 threads. main thread is known as
parent thread and t1 and t2 are known as child threads. Here, the parent
thread is main and it need not be the main, it can be another thread
also. In multithreaded programming, the programmer should see that child
thread dies first and then its creator, parent thread. If not, t1 and t2
become orphan threads and output may differ (again depends on the
processor speed). Then, how to make the parent thread to die always later
than the child. Call simply join() method on the child thread. join()
method is an instruction to the JVM to see that parent thread should not
be allowed to die before child dies, even if the parent thread completes
its job early.

e.printStackTrace();

It is another style of printing the system defined exception message.

Java thread join() ::

join() method of Thread class is little bit confusing for a novice to


understand straight away. I give in my own style with the aim "Java Made
Simple". One thread creates another. See the following code.

public class Demo extends Thread


{
public static void main(String args[])
{
Demo d1 = new Demo();
}
}
Here, we call d1 as thread of Demo class as Demo extends Thread. d1 is
created in main() method. For us, main() is known as a method, but it is
internally a thread. That is, d1 thread is created in the context of main
thread. "d1" is known as "child thread" and "main" is known as "parent
thread". Here, parent thread happens to be main, but it can be any other
thread also. See the next code.

See also this code.

class Test extends Thread { }

public class Demo extends Thread


{
static Test t1;
public void run()
{
t1 = new Test();
}
public static void main(String args[])
{
Demo d1 = new Demo();
d1.start();
}
}
In the above code, run() is implicitly called by d1. That is, d1 is
executing run() method. In run(), t1 thread of Test is created. Now, "d1"
is called as "parent thread" and "t1" is known as "child thread".

After understanding, parent and child threads, who has to die first?

Three options are given.

Who ever finish its job, it can die without waiting for the other.
Parent should not die until child dies even though parent finishes its
job earlier.
Child should not die until parent dies even though child finishes its job
earlier.
A learner having OS knowledge and daemon processes etc., will definitely
say the option b – that is, parent should not die until child dies. Even
the parent finishes its job long before, should wait until its child
dies. Child first and then only parent should die. This is correct way of
using threads. Then, how to accomplish this in Java. Very simple to prove
Java is simple, the answer is join() method defined in Thread class.

class Test extends Thread { }

public class Demo extends Thread


{
static Test t1; // declare static to call from main()
method
public void run() // or else, not required
{
t1 = new Test();
}
public static void main(String args[])
{
Demo d1 = new Demo();
d1.start();

try
{
t1.join();
}
catch(InterruptedException e)
{
System.out.println(e.getMessage());
}
}
}
t1.join() calling from main() method, instructs JVM not to allow d1 to
die before t1 dies.
Now, tell me what is join() method? Let us generalize our concept. join()
will not allow one thread to die before another. It is a communication
between two threads like between a parent and child.

Still, you require more explanation with a good example where output
difference comes if join() is not used, write in the comments box down.

e.getMessage()

The exception object message can be given in three ways. Explained in


getMessage() & printStackTrace().

Thread Priorities:::

Introduction

Thread scheduling of waiting threads, to the processor, is done by the


thread scheduler. Thread scheduler is part of the OS and different
operating systems come with different scheduling algorithms. When some
threads are to be executed before the other, a programmer can give
priorities to the threads. As per the priorities, the scheduler schedules
the waiting threads. The thread with more priority is given the first
preference to the processor than the low priority thread.

A thread can be given 10 priorities starting from 1 to 10 (both


inclusive). To give the priority, the thread class comes with three
symbolic constants, defined in Thread class, as given under.

public static final int MIN_PRIORITY = 1


public static final int NORM_PRIORITY = 5
public static final int MAX_PRIORITY = 10
Two methods exist in Thread class to set the priority and get the
existing priority.

int getPriority() : To retrieve the priority.


void setPriority(int) : To give the priority.
The next program uses the constants and methods to write the priorities.

public class HighLess extends Thread


{
public void run( )
{
for(int i = 0; i < 10; i++)
{
System.out.println(this.getName( ) + ": " + i);
}
}

public static void main(String args[])


{
HighLess hl1 = new HighLess();
HighLess hl2 = new HighLess( );
// setting
priorities
hl1.setPriority(Thread.MAX_PRIORITY-1); // 9

hl2.setPriority(Thread.MIN_PRIORITY+1); // 3
// setting the names
hl1.setName("High"); // for 8 thread
hl2.setName("Less"); // for 3 thread

// to retrieve the priorities


System.out.println("High Priority is " +
hl1.getPriority()); // prints
9

System.out.println("Less Priority is " + hl2.getPriority()); //


prints 3

hl2.start(); // wantedly hl2 is started first


hl1.start();
}
} // you can use join() method also

String threadName = Thread.currentThread().getName();

This statement retrieves the name of the running thread. It is in


abridged form and can be written with more understandability (with two
statements) as follows.

Thread t1 = Thread.currentThread();
String s1 = t1.getName();

currentThread() of Thread class refers the thread running presently


(currently) the run() method. Thread object t1 refers either ml1 or ml2.
It becomes like ml1.currentThread() internally and returns a thread
object which contains the reference of ml1. ml1.getName() returns the
name of ml1. This approach (of getting a thread object) is better when
more properties of Thread are required like t1.getPriority(),
t1.isDaemon() etc.

The thread name can also be obtained as follows (as used in earlier
programs).

String s1 = this.getName();

With the following two statements, names are given to threads and these
names are used in run() method to distinguish the threads which is
executing the run() method.

ml1.setName("Less");
ml2.setName("More");

With the following two statements, priorities are given to threads.

ml1.setPriority(Thread.MIN_PRIORITY+1);
ml2.setPriority(Thread.MAX_PRIORITY-1);

Thread ml1 is given a priority of 2 (1+1) as MIN_PRIORITY is evaluated to


1 at runtime. Similarly, ml2 priority is evaluated to 9 (10-1) as
MAX_PRIORITY is evaluated to 10 at runtime.

ml1.start(); ml2.start();
Purposefully, the thread with less priority, ml1, is started first. But
still, ml2 starts first that got higher priority. Observe the screenshot.

Life cycle of Thread:::

Generally, the life cycle gives the same meaning for servlets, applets
and threads. Different states, a thread (or applet/servlet) comes under
from its object creation to object removal (garbage collection) is known
as life cycle of thread (or applet/servlet). There are four main states
in the life cycle of thread.

Born state
Runnable state
Blocked state
Dead state
The diagram given below, gives a bird view of the states.

1. Born state

Thread t1 = new Thread();


In born state, the thread object is created, occupies memory but is
inactive. In the above statement t1 thread is created but is not eligible
for microprocessor time as it is inactive. To make the thread active,
call start() method on the thread object as t1.start(). This makes the
thread active and now eligible for processor time slices. This state can
be compared with start() method of applets.

2. Runnable state

When the thread is active, the first and foremost job, it does
implicitly, is calling run() method. When the thread is executing the
run() method, we say, the thread is in runnable state. As it is a
callback method, all the code expected to run by the thread, should be
written here. In this state, the thread is active. This state can be
compared to the paint() method of applets.

3. Blocked state

The programmer can make a running thread to become inactive temporarily


for some period. In this period (when inactive after starting), the
thread is said to be in blocked state. The blocked state thread, as
inactive, is not eligible to processor time. This thread can be brought
back to the runnable state at any time. A thread can go a number of times
from runnable state to blocked state and vice versa in its life cycle.
This state can be compared with the stop() method of applets.

4. Dead state

When the execution of run() method is over, as the job it is meant is


done, it is brought to dead state. It is done implicitly by JVM. In dead
state, the thread object is garbage collected. It is the end of the life
cycle of thread. Once a thread is removed, it cannot be restarted again
(as the thread object does not exist). This state can be compared with
destroy() method of applets.

A thread can be killed and brought to dead state, anytime from any state,
by calling explicitly stop() method.
Number of ways a thread can be brought to blocked state

A normal running thread can be brought, a number of ways, into blocked


state, listed hereunder.

By calling sleep() method.


By calling suspend() method.
When wait() method is called as in synchronization
When an I/O operation is performed, the thread is implicitly blocked by
JVM.
IllegalStateException: This exception is thrown when you try to start a
thread which is already started.

Suspending and Resuming a Thread:::

Introduction

When the sleep() method time is over, the thread becomes implicitly
active. sleep() method is preferable when the inactive time is known
earlier. Sometimes, the inactive time or blocked time may not be known to
the programmer earlier; to come to the task here comes suspend() method.
The suspended thread will be in blocked state until resume() method is
called on it. These methods are deprecated, as when not used with
precautions, the thread locks, if held, are kept in inconsistent state or
may lead to deadlocks.

Note: You must have noticed, in the earlier sleep() method, that the
thread in blocked state retains all its state. That is, attribute values
remains unchanged by the time it comes into runnable state.

The following program illustrates the usage of suspend() and resume()


methods.

public class SRDemo extends Thread


{
public void run()
{
try
{
for( int i = 0; i < 7; i++ )
{
Thread.sleep(500);
System.out.println( this.getName() + ": " + i );
}
}
catch( InterruptedException e )
{
e.printStackTrace();
}
}
public static void main( String args[ ] )
{
SRDemo srd1 = new SRDemo();
SRDemo srd2 = new SRDemo();
srd1.setName("First");
srd2.setName("Second");
srd1.start();
srd2.start();
try
{
Thread.sleep( 1000 );
srd1.suspend();
System.out.println("Suspending thread First");
Thread.sleep( 1000 );
srd1.resume();
System.out.println("Resuming thread First");

Thread.sleep(1000);
srd2.suspend();
System.out.println("Suspending thread Second");
Thread.sleep(1000);
srd2.resume();
System.out.println("Resuming thread Second");
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}

Observe the screenshot, when no thread is suspended both threads are


under execution. When First thread goes into suspended state, the Second
thread goes into action. Similarly, when the Second goes to suspended
state, the First is executed.

Note: When you compile this program, you will get deprecated warning. But
the program works happily.

Note: Depending on the microprocessor speed and OS architecture, you may


get a different output or different outputs at different times of
execution. But do not worry.

Miscellaneous Thread Methods:::

So far, we studied the methods like sleep(), start() and currentThread()


etc. of Thread class. Let us study some more methods through the
following example.

public class MoreMethods


{
public static void main(String args[])
{
Thread t1 = new Thread();
System.out.println("t1 name by default: " + t1.getName()); //
given Thread-0
t1.setName("tax");
System.out.println("t1 name after a name is given: " +
t1.getName()); // gives tax

System.out.println("t1 priority by default: " +


t1.getPriority()); // prints 5
System.out.println("Thread group t1 default:" +
t1.getThreadGroup()); // pints main

t1.setPriority(Thread.NORM_PRIORITY+3);
System.out.println("t1 priority after setting: " +
t1.getPriority()); // 8
System.out.println("t1 is daemon by default: " + t1.isDaemon());
// false
t1.setDaemon(true);
System.out.println("After making daemon, t1 is daemon: " +
t1.isDaemon()); // true

System.out.println("t1 is alive: " + t1.isAlive());


// false
System.out.println("t1 is interrupted: " + t1.isInterrupted());
// false
}
}

A thread by default, at the time of brith, comes with three properties


which can be changed by the programmer if needed.

Name: Every thread created gets by default a name. The first thread
created gets Thread-0, the next one as Thread-1 and so on. With setName()
method, a thread can be given a name and with getName() method, a
thread's name can be retrieved.
Priority: Every thread created gets by default a priority of 5, known as
NORM_PRIORITY. A thread can be given a priority with setPriority() method
and a thread's priority can be retrieved with getPriority() method.
ThreadGroup: Every thread created should belong to some thread group. A
thread group should be assigned to a thread at the time of creating the
thread itself. If the programmer does not mention any group, the thread
is placed in the default main group. Once a thread group is assigned, it
cannot be reassigned to another group later. ThreadGroup is a class from
java.lang package.
isAlive() method returns a boolean value. A programmer can create a
number of threads of which a few may be active, some inactive and the
other might have dead. To know the state of a thread, a programmer can
use isAlive() method. This method returns true if the thread is in
runnable state or blocked state. In born state and dead state, the method
returns false.

isInterrupted() method returns true if the thread state (like execution


or blocked time) is disturbed.

Daemon Threads

Daemon threads are service-oriented threads. A service-oriented thread,


as the name indicates, serves all other threads. They die after every
thread in the process dies, or to say, just before the process exits (no
way related with the run() method execution). They are created before any
thread is created and dies after every thread dies. For example, the JVM
comes with a service thread, garbage collector which removes the garbage
(unwanted objects etc.) generated while the process is going on.

The daemon threads are given lowest priority as they should come into
action when no other thread is active as process execution (that gives
output) must be of highest priority. A normal thread can be converted
into a daemon thread with the following simple statement.

t1.setDaemon(true);

The boolean value true indicates t1 should be converted into a daemon


thread. If false or if the statement is completely omitted, the thread is
a non-daemon thread.
t1.isDaemon();

To test a thread is daemon or not, isDaemon() method is useful. It


returns true if the thread is daemon, else false.

Inter thread communication

Communication between the threads can be done with join() method (between
a parent and a child) and wait() and notify() methods (between a thread
that locked the source and the other waiting for the lock).

Synchronization and Deadlock::

Introduction – Basics

Generally, one thread accesses one source of data (or to say, its own
source) like your thread accesses your bank account. Sometimes, it may be
needed multiple threads to access the same source of data like all the
partners of a business may be acting on the joint bank account at the
same time. When multiple threads access or share, there may be data
corruption or inconsistency.

To avoid data inconsistency, a concept called synchronization comes. The


literature meaning of synchronization is putting the events in an order.
synchronized is a keyword of Java used as access modifier. A block of
code or a method can be synchronized. The advantage of synchronization is
only one thread is allowed to access the source and other threads are
made to wait until the first thread completes its task (of accessing the
source). This is known as a thread safe operation.

Synchronization is a way of inter-thread communication (another is


join()). In the following snippet of code, whole method is synchronized.

public synchronized void update(int account, double


withdrawAmount)
{
// some JDBC code
balance = balance - withdrawAmount; // 1st
statement
System.out.println("Best Wishes"); // 2nd
statement
}
In the following snippet, only one line of code is synchronized and all
the remaining code is untouched (not synchronized).

public void withdraw(int account, double withdrawAmount)


{
synchronized(this)
{
// some JDBC code
balance = balance - amount; // 1st statement
}
System.out.println("Best Wishes"); // 2nd statement
}
Synchronization makes a program to work very slow as only one thread can
access the data at a time. Designers advice to synchronize only the
important and critical statements of the code. Do not synchronize
unnecessarily.

In the above code, first statement is critical and the second is not. For
this reason, in the second snippet, only first statement is synchronized.
This increases the performance to some extent.

More on Synchronization – Thread Regulation

To explain the affect of synchronization, a small program is taken where


100 threads are created and iterated 10,000 times each. Each iteration
increments the variable k by one and decrements by one. That is, at the
end, the value should not be changed; should remain as zero, the default
value for an unassigned instance variable.

public class SynchDemo implements Runnable


{
static int k; // value
default is 0
public void run()
{
synchronized(this)
{
for(int i = 0; i < 10000; i++)
{
k++; // increments by one
k--; // decrements by one
}
}
}
public static void main(String[] args) throws Exception
{
SynchDemo sd = new SynchDemo();
Thread bundle[] = new Thread[100];
for(int i = 0; i < bundle.length; i++)
{
bundle[i] = new Thread(sd);
bundle[i].start();
}
System.out.print("Final result: " + k);
}
}

An array of 100 threads by name bundle is created. In a for loop they are
initialized and started. In each iteration k is incremented and at the
same time decremented, so that the value of k is unchanged.

The screenshot displays k is always 0 for any number times of execution.


Just remove, the synchronized(this) statement and observe different
outputs. Why this happens? How synchronization mechanism works
internally? Let us see.

wait(), notify() and notifyAll()

These methods are defined in Object class inherited by every class so


that every Java class can make use of these methods. When a thread
accesses the synchronized code, the JVM calls wait() method. With this
method call, the resource is locked so that no other thread is allowed to
access. All the threads requiring the resource should wait in a queue
outside. When the accessing thread job is over, it calls notify() or
notifyAll() method and thus relinquishes the lock. Now JVM allows one of
the waiting threads to access the resource. Again this thread calls
wait() method and locks. As only one thread is allowed to access, the
program runs very slow. wait(), notify() and notifyAll() methods are
useful with synchronization only; outside they do not have any meaning.
The electronics people say, the synchronization is nothing but applying
monitor concept.

Remember, Vector methods are synchronized and ArrayList methods are not.
Similarly, StringBuffer methods are synchronized and SringBuilder methods
are not. Now the programmer has got choice to choose depending on the
code necessity. Synchronization mechanism is very useful to control the
scheduling of threads.

Starvation and Deadlock

These are the two problems that may creep into the programming code if
the programmer is not aware of these concepts.

Your style of programming should allow fairly each thread to get


microprocessor time; this is known as fair system. A fair system does not
allow a thread to get starved of processor time. A starved thread is the
one that does not get processor for a long time. A starved thread cannot
give the output fast.
After starvation, another problem with threads is deadlock. When one
thread depends on another for their execution, a deadlock occurs. When
two threads are holding locks on two different resources, one thread
would like to have other's source, a deadlock occurs. Deadlock is the
result of poor programming code and is not shown by a compiler or
execution environment as an exception. When exists, the program simply
hangs and programmer should take care of himself.
Note: A class as a whole cannot be synchronized. That is, synchronized
class declaration raises compilation error.

ThreadGroup – Grouping of threads:::

We know earlier, every thread should belong to some thread group and if
no group is mentioned, the thread is placed, by default, in main thread
group. When the JVM starts a new process, it creates main thread group
and every thread created by the programmer, if not mentioned any group,
the JVM keeps the thread in the main thread group. The programmer can
explicitly mention a thread group also where the thread is to be placed.
But remember, the thread should be placed in a group at the time of
creating the thread only; else it is placed in main thread group
implicilty. Once a thread is allotted a thread group, throughout its
life, the group cannot be changed.

By placing the thread in a group, the advantage is, the thread attains
the properties of the group implicitly. For example, any thread belonging
to main thread group attains a default priority of 5 because main group
priority is set to 5. The java.lang package includes ThreadGroup class to
manipulate the threads with groups.

Placing Threads in ThreadGroup


With the above knowledge of thread groups, now let us write a program
where a thread is created, placed in a group and its properties are set
explicitly.

public class ThreadGroupInfo


{
public static void main(String args[])
{
ThreadGroup tg1 = new ThreadGroup("FinanceGroup");

System.out.println("tg1 name: " + tg1.getName());


System.out.println("tg1 parent group: " + tg1.getParent());
System.out.println("tg1 priority, by default: " +
tg1.getMaxPriority());
tg1.setMaxPriority(Thread.NORM_PRIORITY+3);
System.out.println("tg1 priority after setting: " +
tg1.getMaxPriority());
System.out.println("Active threads in the tg1 group: " +
tg1.activeCount());

Thread t1= new Thread(tg1,"RevenueThread");


System.out.println("Thread t1 Name: " + t1.getName());
System.out.println("t1 group: " + t1.getThreadGroup());
}
}

Let us discuss some methods of ThreadGroup used in the above program.

ThreadGroup tg1 = new ThreadGroup(“FinanceGroup”);

A thread group by name FinanceGroup is created. The programmer can


retrieve the name of the group with getName() method. getParent() method
returns the parent thread group of FinanceGroup. Any group created by the
programmer is placed in main thread group by the JVM implicitly. This is
how the JVM controls the user-defined thread groups. getMaxPriority()
returns the maximum priority, the threads of a group can be assigned.
Observe the screenshot, even though the default priority of main group is
set to 5 implicitly by JVM, the programmer can assign to a maximum of 10
to a thread. Using setMaxPriority() method, the programmer can assign a
priority to a group. In the program it is set to 8 (5+3). The
activeCount() method returns the number of active threads in the group.
It printed zero in the program as we did not place any threads in the
group and started.

Thread t1= new Thread(tg1,"RevenueThread");

In the above statement, a thread by name t1 is created with name


RevenueThread and is placed in the group tg1. It must be observed that a
thread should be placed in a group at the time of creation itself; else,
it is placed in main group and once placed in a group, it cannot be
changed.

Advantages of ThreadGroup

It is learnt earlier that every thread should belong to a group. With


thread group, all the threads in a group can be assigned properties at a
time instead of the laborious way of setting property to each individual
thread separately. Following are the benefits with thread groups.
All the threads can be given a common priority. For example, the common
priority set to all the threads of main group is 5.
All the threads of a group can be stopped, suspended or resumed at a
time, but cannot be started at a time ; each individual thread should be
started separately.
Generally, thread groups are used very less in programming. The
programmer leaves the thread management to the JVM itself.
SecurityManager class should be used to have extra control or
manipulation over the thread groups.

Thread Cancellation and Starvation::

Canceling a Thread

Sometimes, the programmer may require killing a thread from any state.
One example of such a situation is if the thread is taking an unusual
time to complete a task which the programmer cannot bear, it is the time
for him to kill the thread. This is more observed in Web servers. The Web
administrator keeps a timeout period for every task user requests. When
the timeout period is over, he kills the thread to save the resources of
the server.

To cancel a thread, the Thread class includes a method stop(). The stop()
method should be used cautiously because it is going to kill an active
thread. Any lock, the thread if holding, must be cleared first and then
killed; else the data is left inconsistent. For this reason, this method
is deprecated. When you compile the program using stop() method, the
compiler raises a deprecation warning; observe the screenshot.

The following program uses stop() method. The thread is supposed to print
10 numbers, but prints only 6 as stop() method is called after printing 6
numbers.

public class StopInfo extends Thread


{
public void run()
{
for( int i = 0; i < 11; i++)
{
if(i == 7)
{
System.out.println("Sorry, I could not print 7 to 10 as
I am getting killed.");
this.stop();
}
System.out.println("Printing: " + i);
}
}
public static void main(String args[])
{
StopInfo si1 = new StopInfo();
si1.start();
}
}

The following statement kills the thread when the counter i is 7. When
killed, it does not print 7 to 10;
this.stop();

The println() method before the above statement is printed as it is


called before killing the thread. Observe the screenshot for deprecation
warning at compilation.

Starved threads – Yielding the Processor

We know earlier, the thread scheduler is OS dependent and is a very


complex algorithm, executed very frequently. Whenever, a new thread joins
the pool of waiting threads or leaves the pool (when blocked or dead),
the order of priorities changes and the scheduler recalculates the
scheduling again.

In the rescheduling, some threads may not get a chance of processor for a
long time. These threads are known as starved threads. To request the JVM
to get the processor time (which may not be obliged), the programmer can
use yield() method. The yield() method temporarily stops the execution of
a thread for a while. When stopped, the scheduler recalculates the
scheduling as the order changes. In the recalculation, a starved thread
may get a change of processor time; but not guaranteed. The programmer
cannot force the JVM to allocate the processor time for a starved thread
(like he cannot force garbage collection to take place). It does not
imply any meaning, calling yield() method, when no other thread exist for
execution.

public class YieldTest extends Thread


{
public void run()
{
for( int i = 0; i < 6; i++)
{
System.out.println("Number: " + i);
this.yield();
}
}
public static void main(String args[])
{
new YieldTest().start();
}
}

In the above code, yield() method is called for every iteration. Of


course, this type of coding is uncommon; it is an example to show how to
use yield() method.

this.yield();

Using yield() method number of times decreases the performance. In the


above statement, this refers an object of current thread calling the
run() method.

new YieldTest().start();
In the above statement, an anonymous object of YieldTest is created and
start() method is called. This saves memory of an object.

Java Thread Scheduler::

In Java program, you create threads but they are not executed by Java
alone. Java takes the help of the underlying OS to execute them. To
allocate microprocessor time and to supervise all the threads' execution,
the OS comes with Thread Scheduler. The entire responsibility of
maintaining the sequence of execution of threads, where which thread
should be given first preference than the other, lies with the thread
scheduler. The scheduling depends on the algorithm of the scheduler. Many
types of algorithms exist like preemptive and time slicing with round
robin etc. It is a very complex algorithm that executes many times in a
given time.

The scheduler maintains a pool of threads. When Java thread is started


calling start() method, it joins the pool of waiting threads. For
deciding processor allocation for each waiting thread, the scheduler
takes many aspects into consideration.

1. Priority of thread
2. Waiting time of thread
3. Nature of thread

The JVM is based on preemptive and priority based scheduling algorithm.


The thread with more priority is given first preference than the thread
with less priority. The thread with more priority relinquishes (empties)
the thread with less priority that is being executed. If the threads of
equal priority are in the pool, the waiting time is taken in
consideration. Nature of threads sometimes affects. The daemon threads
are given less importance and are executed only when no other thread is
available for execution.

When JVM starts executing a Java program, it creates a few threads for
the execution.

1. main is a method for us, but main is a thread for JVM. The execution
starts with main thread.

2. Garbage collector is a daemon thread that comes into action before


every thread.

3. Event Dispatcher is a thread which will take care of events raised by


the components like click of a button etc.

4. There is one more, Timer thread, which maintains the time for methods
like sleep() etc.

When a thread is started with start() method, the Java thread joins the
pool of waiting threads. It does not mean the scheduler should give the
processor time immediately. "Joins" means, it is guaranteed of getting
processor time, but at what time depends on the decision of the scheduler
managed by the OS. When a thread joins, the scheduler is executed by the
OS and makes a table of threads' sequence to allocate processor time.
When a sleep() method is called, the thread is removed from the active
pool, then again the scheduler is executed to make the table as there
comes imbalance in the waiting threads. And executed again when the
thread joins the pool when the sleep() time is over. For this reason, the
scheduler executes a number of times when a thread joins, yields, stops
or leaves (when blocked or dies) the pool.

How to create multiple threads as Heavyweight Process in Java?

We know earlier how to create single threads by extending Thread class


and also by implementing Runnable interface. Now let us create multiple
threads of different processes and execute them. Before going further,
let us know what is lightweight process and heavyweight process. It is
very necessary in multiple threads execution.

What is Lightweight process and Heavyweight process?

Advantage of multithreading is to reduce the microprocessor’s idle time


so that the response to the user gets earlier.

If the execution control is shifted between the threads of the same


process it is known as lightweight process and if the control is shifted
between the threads of the different process, it is known as heavyweight
process.

As you can guess, the lightweight process has more performance than
heavyweight process. Generally, threads are designed to be lightweight
process.

The following program is an example on heavyweight process wherein two


threads t1 and t2 of two different processes of Test1 and Test2 are
created executed simultaneously. If t1 is blocked (or stopped or
inactive) its execution, the t2 execution starts and similarly if t2
stops its execution, t1 starts (active).

Aim: To create two threads of different classes (heavyweight process)


that prints 0 to 99 and 99 to 0 alternatively.

class Test1 extends Thread // prints 0 to 99


{
public void run()
{
for(int i = 0; i < 100; i++)
{
System.out.println("Test1: " + i);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Some problem. " + e);
}
}
}
}

class Test2 extends Thread // prints 99 to 0


{
public void run()
{
for( int i = 99; i >= 0; i--)
{
System.out.println("Test2: " + i);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Some problem. " + e);
}
}
}
}

public class TwoRuns


{
public static void main(String args[])
{
Test1 t1 = new Test1();
Test2 t2 = new Test2();

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

try
{
t1.join();
t2.join();
}
catch(InterruptedException e)
{
System.out.println("Some problem. " + e);
}
}
}
ima

Clear explanation on the above code along with lightweight process


example is given at Heavyweight and Lightweight Threads

Java Made Simple: Create Array of Threads with Example

After knowing how to create multiple threads (both lightweight and


heavyweight), let us modify the code to suit for creation of multiple
threads as an array.

In the following code an array of 5 threads is created and started. Being


lightweight, all threads call the same run() method. In the run() method,
a sum value is added with i value of for loop; a simple code to get the
concept of array of threads.

class Test extends Thread


{
static int sum;
public void run()
{
for(int i = 0; i < 10; i++)
{
sum += i;
}
}
}
public class ArrayOfThreads
{
public static void main(String args[])
{
Test test[] = new Test[5];
for(int i = 0; i < test.length; i++)
{
test[i] = new Test();
test[i].start();
}
System.out.println("Sum = " + Test.sum);
}
}
ima

Test test[] = new Test[5];

In the above statement, five threads test[0], test[1] etc. are not thread
objects; they are reference variables. That is, test[] is an array of
reference variables of Test class but not array objects Test class. They
must be converted into array objects and this is done in the next
statement.

test[i] = new Test();


test[i].start();

new Test() converts each reference variable into array object. When
converted into object, start() method is called on the thread object so
that it calls the callback method run().

What is yield in Java threads and how it differs from sleep?

Scheduling the threads to the Microprocessor for execution, one after


another, is entirely the responsibility of the underlying operating
system. The scheduler (controlled by OS or part of OS) considers many
factors of the waiting thread while allocating Microprocessor time like
waiting time, priority and nature (like daemon). Scheduler is of very
complex algorithm executed number a times in a small period whenever a
thread joins the pool of waiting threads or leaves (for blocked state or
dead state). In this calculation and recalculation, some thread may not
get a chance of Microprocessor for a considerable time. This type of
thread is known as "starved thread" – starving for a long time for
Microprocessor.

Programmer is not given any handle to dictate the scheduler. Then, is


there any way to get a chance of processor time for a starved thread. The
answer is "yield()" method.

Following is the method signature of yield() method as defined in


java.lang.Thread class.

public static native void yield();


yield() is a static method that can be applied on a running thread (like
static method sleep()) only. When yield is called, as Thread.yield(), the
current thread (or running thread) is halted (or paused) its execution
for a while (imagine, like calling sleep(1)). We know when a thread is
halted its execution, again scheduler makes a fresh allocation table on
the waiting threads. In this fresh table preparation, the starved thread
may get a chance of processor time. It is only a chance but no
compulsion. Following is the snippet of code.

public void run()


{
for(int i = 0; i < 10; i++)
{
if(i == 5)
{
Thread.yield();
}
}
Writing the code like this is optional and left to the discretion of the
Programmer.

Differences between yield() and sleep():

It differs from sleep() in that sleep() takes a long parameter and


yield() carries no parameter.
yield time is not in the hands of Programmer where as sleep() time is.
It is advised to use sleep() instead of yield() to halt or stop the
execution of a thread for a while. Blocked time is in Programmer’s
control with sleep() method.
yield() is given to Programmer to give a chance to other threds to
execute. sleep() is given to stop current thread execution.
yield() method voluntarily gives up (or stops temporarily) the execution
of the current thread giving chance to other threads waiting for
processor’s time. If no other threads are waiting or other threads have
lower priority, the execution proceeds with the same thread. But sleep()
method stops the execution for the specified time eventhough no other
waiting threads exist.
sleep() suspends the execution for a specified number of milliseconds
where as yield() makes the thread to join the pool of waiting threads (or
joins the queue of waiting threads at the last).
The implementation of yield() method is scheduler (or OS) dependent.

Java Made Simple: join() method with Example and Explanation

It is very cofusing for a novice, the difference between join(), yield(),


sleep(), suspend() and wait() methods in Java thread management. Here we
go with join() method. To understand easily, I take the example of parent
and child threads.

One thread creates another thread. The thread which creates is known as
parent thread and the one getting created is known as child thread. The
question here is who should die first. Is it first parent then child or
other way or who ever finish its job it may die? Any rule exists? Here, I
give an example from our daily life.

A mother walks with her baby child of just 4 years age to nearby
vegetable market by catching baby’s hand. While bargaining with the
vendor, she forgot the child and lost her hand. The child moves while
crying. Get the same child and leave at the same spot. Does she move in
the same direction while crying or in other direction? She moves in a
different direction. If the child does not leave mummy’s hand, the
direction is fixed – from house to market and from market to house. Here,
the child is called as orphan child. The orphan child moves eccentrically
in different direction each time when left alone. So the child should be
with mummy always. If mummy dies first, the child becomes orphan. So, the
child should die first and then the parent.

This above example applies to our threads also. If parent thread dies
first, the child thread becomes orphan thread. Orphan thread moves
eccentrically when called different times. If a parent thread comes to
die (as its assigned job is finished) before its child dies, it should
not be allowed. It is good coding in multithreading. How to do the job?
The answer is join() method. It is an instance method (should be called
with a thread object) defined in Thread class.

Following is the method signature as defined in Thread class

public final void join() throws InterruptedException;


public final synchronized void join(long milliseconds) throws
InterruptedException;
public final synchronized void join(long milliseconds, int nanoseconds)
throws InterruptedException;
The join() method is overloaded which sometimes takes time period also.
Like sleep(), join() also throws a checked exception –
InterruptedException.

Last two join() methods are not much used, where you specify the time
period to wait, because join() method timing is OS dependent where join()
will exactly may not wait the time period you specify.

Calling join() method on a thread, until the thread dies, its parent
thread is not allowed to die by the JVM even it completes its job and
ready for die – a communication between two threads.

Let us see a simple program to know which is parent and which is child.

class Test extends Thread


{
public void run()
{
for(int i = 0; i < 3; i++)
{
System.out.println("Test: " + i);
}
}
}

public class Demo extends Thread


{
public void run()
{
Test t1 = new Test();
t1.start();

for(int i = 0; i < 3; i++)


{
System.out.println("Demo: " + i);
}
try
{
t1.join();
}
catch(InterruptedException e) { e.printStackTrace(); }
}
public static void main(String args[])
{
Demo d1 = new Demo();
d1.start();
}
}
In the above code, two threads exist – d1 of Demo class and t1 of Test
class. In the run() method of d1, t1 of Test is created. That is, t1 is
created in the context of d1. d1 is called as parent thread and t1 is
called as child thread. Calling of t1.join(), the JVM does not allow d1
to die before the death of t1. Calling join() method is always a good
programming paradigm.

One parent thread can create lot of child threads (in the above, only one
t1 is created and started) and should wait until all the child threads
die (complete their execution).

Let us see some more ways of explaining join() method

The join() method permits one thread to wait until the completion of
another thread.
The join() method waits (does not die) for the death of another thread.
A thread can be in waiting state until other thread terminates its
execution.

Java Made Simple: What is isAlive() in Java with Example?

A Programmer may create hundreds of threads of which some may be in born


state, some in runnable state, some in blocked state and some in dead
state (all these are known as life cycle methods). He would like to know
which thread is still running in the process. The answer is isAlive()
method defined in Thread class. It is an instance method (not static) and
thereby should be called with a thread object only. The isAlive() method
returns true if the thread is in runnable state or blocked state else
returns false.

Following is the method signature as defined in Thread class

public final native boolean isAlive();

Following is a simple code using isAlive() method.

public class Demo extends Thread


{
public void run()
{
Thread t1 = Thread.currentThread();
System.out.println("From run, status = " + t1.isAlive());
}
public static void main(String args[])
{
Demo d1 = new Demo();
d1.start();
try
{
d1.join();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println("From main, status = " + d1.isAlive());
}
}
ima

In the above code, d1 thread of Demo class is created and started. In the
run() method t1 refers the current thread that is right now executing the
run() method. Obviously, it is d1 as d1 is calling the run() method. The
status of d1 in run() is true and in main() method is false. Calling
join() waits the parent thread main not to die until the child d1 dies.

Some more definitions

A thread is said to be alive (where isAlive() returns true) when is has


been started and still not died.
isAlive() method returns true if the thread (upon which it is called) is
still running and not finished.
isAlive() checks if the thread is alive and executing.
The Thread class comes with an instance method (that is to be called with
an object) isAlive() to determine whether the thread is in born state or
dead state where calling isAlive() returns false (here, isAlive() informs
the thread is not running now or stopped).
isAlive() is used to know if a thread is actually started and not yet
terminated its execution.
isAlive() is very less used and more common is join() usage.
Note: Java does not have a method to determine whether the thread is in
born state or dead state.

What is difference between Process and Thread and Program? •

A Program when started execution is known as Process. Or to say, a


program under execution is known as Process (some people call it as a
task). Process occupies some memory space for execution. OS gives a
unique process identifier, known as PID, for each process.

A program can be divided into a number of threads. Each thread comprises


of a block of statements. A thread also requires some memory space for
execution, but the space is allotted within the memory space of the
process. If 100 threads exist, all 100 threads takes their execution
space within the process memory space (share the process memory space)
only. It can be said, a thread is a sub-process or a small process within
a process. Each thread have its own stack, registers and counter in Java.

Because all threads of the process executes within the same memory space
(of process), their execution is faster. A programmer can shift the
control between the threads of the same process and is known as
lightweight process. Similarly, there may be another process with
threads. If the execution control is shifted between the threads of
different processes, it is known as heavyweight process. Obviously,
lightweight threads are faster than heavyweight and for this reason, the
threads are designed mostly as lightweight by the Programmer.

All threads within a process executes independent of each other. If


required, threads can communicate with other (inter process
communication) in Java, with wait() and notify() etc.

Difference between thread start() and run() in Java

First let us see the two codes of calling start() and run() methods with
screenshots. The observation of screenshots itself tells the difference
and what to be used.

This is the normal code calling start() method on the thread.

public class Demo extends Thread


{
public void run()
{
System.out.println("Thread Status alive: " + this.isAlive());
}
public static void main(String args[])
{
Demo d1 = new Demo();
d1.start();
}
}
ima

This is the abnormal code calling run() method on the thread.

public class Demo extends Thread


{
public void run()
{
System.out.println("Thread Status alive: " + this.isAlive());
}
public static void main(String args[])
{
Demo d1 = new Demo();
d1.run();
}
}
ima1

Observe, both the screenshots. With start() method, the thread isAlive()
method returns true and with run() method, the thread isAlive() returns
false. What does it indicates; in both the styles, thread is created and
run() called. With start() style, the JVM implicitly calls run() method
in run() method, the thread d1 being executed. For this isAlive()
returned true. If start() is called, the JVM maintains the life cycle of
thread and does many activities on the thread, thread is eligible.

By calling run() method directly as d1.run(), as in the second case, it


is equal to simply a normal method call. in d1.run(), d1 is assumed, by
JVM, as an object of Demo class but not thread of Demo class. That is,
run() is not called or executed by a thread. For this reason, isAlive()
returned false.

So use always d1.start() and not d1.run().

Some salient points to understand better the concept

If start() is called, the thread is activated and run() method is


executed in the context of this thread. For this reason, the first
screenshot gives true. If run() is called directly, the run() is executed
in the context of some different current thread, may be of JVM like main
thread. As different thread is executing run(), the second screenshot
gives false.
start() method in Java is declared native having implemented natively.
That is, start() method calls and communicates with underlying OS thread
management system. Following is the signature of start method.
public native synchronized void start();

The JVM assigns the responsibility of calling run() method to thread


scheduler entirely managed by OS. The scheduler calls the run() method at
its discretion as per the priority, waiting time and availability of
processor time etc.

Calling run() does not create or go with a new thread.


Invoking run() directly is just calling a method but not starting a
thread.

Daemon Thread in Java Example:::

Daemon threads are service-oriented threads. A service-oriented thread,


as the name indicates, serves all other threads. They die after every
thread in the process dies, or to say, just before the process exits (no
way related with the run() method execution). They are created before any
thread is created and dies after every thread dies. For example, the JVM
comes with a service thread, garbage collector which removes the garbage
(unwanted objects etc.) generated while the process is going on.

The daemon threads are given lowest priority as they should come into
action when no other thread is active as process execution (that gives
output) must be of highest priority. A normal thread can be converted
into a daemon thread with the following simple statement.

t1.setDaemon(true);

The boolean value true indicates t1 should be converted into a daemon


thread. If false or if the statement is completely omitted, the thread is
a non-daemon thread.

t1.isDaemon();

To test a thread is daemon or not, isDaemon() method is useful. It


returns true if the thread is daemon, else false.

Salient points with daemon threads

When the parent is daemon, the child thread also gets the status of
deamon.
Daemon threads should not be used with regular operations like I/O and
transaction management (which are not atomic) etc.
Daemon threads are executed at the background with supporting tasks (like
handling requests) needed for the execution of normal threads and can be
assigned the responsibility of managing resources.
A process exits after all threads finish their job and only daemon
threads remain.
Daemon threads always given the least priority of 1.
Daemon thread will be exeucted when no other thread is running.
Properties to a thread like setting daemon and priority etc. should be
done before start is called. Once a thread is running, we cannot change
their properties. Sometimes, JVM throws IllegalThreadStateException.
Threads by default are not daemon.
When only daemon threads exist, JVM simply exits without executing
finally blocks and unwind stacks etc.

Java Clear Concepts: Java sleep method Example:::

One of the features of Java is its support for multithreading. A Java


program can be divided into multiple threads and executing each thread
with a different functionality. Sometimes, it may be required to
temporarily stop the thread execution for a specified time. The easiest
way is using sleep() method of Thread class.

Following is the method signature

1. public static native void sleep(long milliseconds) throws


InterruptedException
2. public static native void sleep(long milliseconds, int nanoseconds)
throws InterruptedException

The parameter is time in milliseconds to pause the thread execution. The


second overloaded sleep() method time in nanoseconds depends on the
precision and accuracy of system timers and schedulers.

The sleep() method stops the execution of the right now running thread
(called as current thread) for the specified time. It is declared static
so that it can be called just by class name. "native" means, the sleep()
method execution Java cannot do alone but depends on the underlying
operating system. This method throws a checked exception
"InterruptedException" and should be handled else program does not
compile.

Let us use sleep() method in an example. The following example creates,


starts and executes thread by extending Thread class. The execution
should print 0 to 9 numbers with an interval of 1000 milliseconds (1
second) using sleep(1000).

public class Demo extends Thread


{
public void run()
{
for(int i = 0; i < 10; i++)
{
System.out.println("Iteration: " + i);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Some problem. " + e);
}
}
}
public static void main(String args[])
{
Demo d1 = new Demo();
d1.start();
}
}
ima

Demo d1 = new Demo();


d1.start();
In the above code, d1 is an object of Demo class. But, we can call d1 as
thread of Demo class as Demo extends Thread class. We can say, proudly we
created a thread d1. But the thread d1 is inactive by default. To make it
active, call start() on it. start() is a method of Thread class. When the
thread is active, it calls implicitly run() method. run() is another
method of Thread class.

try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Some problem. " + e);
}
The sleep(1000) makes every iteration to pause (stop) by 1000
milliseconds or to say, the thread is inactivated by 1000 milliseconds.
An inactive thread is not eligible for microprocessor time. sleep()
method is declared static so that it need not be called with object and
also, in Thread.sleep(), the Thread represents the current thread. For
this reason, sleep() is declared as static. sleep() method throws a
checked exception "InterruptedException" and is handled in catch block.

You might also like