Thread Programming

Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

1

THREAD PROGRAMMING
Introduction
A Thread sometimes called a lightweight process (LWP), is a basic unit of CPU utilization, it
comprises a thread ID, a program counter, a register set, and a stack. It shares with other threads
belonging to the same process its code section, data section and other system resources. A traditional
(or heavyweight) process has a single thread of control. If a process has multiple threads of control, it
can do more than one task at a time.
Java is one of a small number of languages that provide support at the language level for the creation
and management of threads. All Java programs comprise at least a single thread of control. Even a
simple Java program consisting of only a “main” method runs a single thread in the JVM. In
addition, Java provides commands that allow the developer to create and manipulate additional
threads of control within the program. Classes and interfaces for creating threads are part of core
java.lang package and the class java.lang.Object, from which all Java objects descend, has methods
to support multithreaded programming. To take advantage of the powerful networking features of
Java, one has to use threads and multithreaded programming in the network programs appropriately.
Address Space
Most modern operating systems can run multiple processes at the same time such as we might run
our email client, editor and compiler all at once. Modern desktop operating system enforce a
separation between the memory areas used by these programs, so a bug in the compiler can’t crash
the editor and the email client can’t break the compiler. Each of these separate memory areas is
called an address space.
Context Switching
The operating system is responsible for scheduling the processes ad managing the address space for
each one. Switching between processes is called context switching and requires the operating
system to save the whole state of the running process. If the computer has more than one processor,
the operating system could even schedule them to run simultaneously. Because the processes are
completely independent, the system as a whole is reliable even if the individual programs are not.
Threads
A process contains one or more independent units of execution called threads. Threads are similar to
processes in that they are independent flows of control, but they are also different in important ways–
 The threads within a process run within a single address space, so the threads operate using
the same body of code and the same body of data.
 Because the threads are operating within a single process, the Java Virtual Machine rather
than operating system can do the thread scheduling. This can make context switching much
more efficient.
Example:
//Program displaying single Thread program
//ThreadTest.java
import java.lang.*;
class ThreadTest
{
public static void main(String[] args)
{
Thread t = Thread.currentThread();
System.out.println(“Mainthread” + t);
t.setName(“Namechange”);
System.out.println(“ChangedThread” +t);

Sapna Saxena, Lecturer, Chitkara University


2
try
{
for(int i=0;i>10;i++)
{
System.out.println(i);
Thread.sleep(500);
}
}catch(InterruptedException e) {}
}
}
Creating and Running a Thread
To run more than one task concurrently, developer can make use of threads. There are two ways to
do this –
 Using a subclass of the Thread class
When the subclass of the Thread class is created, this class should define its own run()
method to override the run() method of the Thread class. This run() method is where the task
is performed.
Just as the main() method is the first user defined method the Java Run Time (JRE) calls to
start an application, that run() method is the first user-defined method, the JRE calls to start a
thread. An instance of this subclass is then created by a new statement, followed by a call to
the thread’s start() method to have the run() method executed.
 Implementing the Runnable interface
The Runnable interface requires only one method to be implemented. Developer should
create an instance of this class with a new statement, followed by the creation of a Thread
instance with another new statement, and finally a call to this thread instance’s start() method
to start performing the task defined in the run() method. A class instance with the run()
method defined within it must be passed in as 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.
Thread Control Methods
Many methods defined in the Thread class control the running of a thread. Here are some most
commonly used methods –
 start() – Used to start the execution of the thread body defined in the run() method. Program
control will immediately returned to the caller and a new thread will be scheduled to execute
the run() method concurrently with the caller’s thread.
 stop() – This is a deprecated method. It is used to stop the execution of thread. The thread is
then considered dead, the internal states of the thread are cleared, and the resources allocated
are reclaimed. Using this method has the potential to leave data in an inconsistent state are
should be avoided.
 suspend() – This is the depracated method. It is used to temporarily stop the execution of the
thread. All the states and resources of the thread are retained. The thread can later be restarted
by another thread calling the resume () method. Using this method has a strong potential for
dead locks and should be avoided. Instead, we can use the object. Wait () method.
 resume () – Deprecated. It is used to resume the execution of a suspended thread. The
suspended thread will be scheduled to run. If it has a higher priority than the running thread,
the running thread will be preempted, otherwise, the just – resumed thread will wait in queue

Sapna Saxena, Lecturer, Chitkara University


3
for its turn to run. Using this method has a strong potential for dead locks and should be
avoided.
 sleep (long milliseconds) – This method causes the Java run time to put the caller thread to
sleep for a minimum of the specified time period. The Interrupted Exception, must be thrown
while a thread is sleeping or any time the interrupt () method is called. Either a try – catch
statement is needed to be defined to catch the exception or the enclosing methods needs to
have this exceptions in throws clause.
 join () – It is used for caller’s thread to wait for this thread to die – for example, by coming
to the end of the run () method.
 yield () – A class method that temporarily stops the caller’s thread and puts it at the end of
the queue to wait for another turn to be executed. It is used to make sure other thread of the
same priority have chance to run.
Thread Priorities and scheduling
Priorities are the way to make sure important or time – critical threads are executed frequently or
immediately. Scheduling is the means to make sure priorities and fairness are enforced.
If there is only one CPU, all of the runnable threads must take turns executing. Scheduling is the
activity of determining the execution order of multiple threads.
Every thread in Java is assigned with a priority value, when there are more than one thread is
competing for CPU time. Thread priority values are simple integers ranging between Threads – MIN
– PRIORITY and Thread. MAX – PRIORITY. User applications are normally run with the priority
value of Thread . NORM – PRIORITY. The constants of Thread class – MIN – PRIORITY, NORM
– PRIORITY – have the values of 1, 5 & 10 respectively.
When a thread is created, it will inherit the priority value of the creating thread if the priority value
doesn’t exceed the limit important by its patent thread group. The set priority () method of Thread
class can be used to set priority value of a thread. The set Max Priority () method can be used to set
the maximum priority value of a thread group. Java’s scheduling is preemptive, i.e, if thread with a
higher priority than the currently running thread becomes runnable. The higher priority thread should
be executed immediately, pushing the currently running thread back to the queue to wait for its next
turn. A thread can voluntarily pass the CPU execution privilege to waiting threads of the same
priority by calling the yield () method.
Example:
//Program displaying Thread methods & thread Priorities
//ThreadPrinting.java
import java.lang.*;
class ThreadPriorityTest.java
{
Int count =0;
Thread t;
private volatile Boolean running = true;
public ThreadPriorityTest() { }
public void run()
{
while(running)
{
count++;
}
}
public ThreadPriorityTest(int p)
{

Sapna Saxena, Lecturer, Chitkara University


4
t = new Thread(this);
t = setPriority(p);
}
public void start()
{
t.start();
}
public void stop()
{
t.stop();
}
}
class ThreadPriniting
{
public static void main(String[] args)
{
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
ThreadPriorotyTest lo = new ThreadPriorityTest(Thread.NORM_PRIORITY(-2));
ThreadPriorotyTest hi = new ThreadPriorityTest(Thread.NORM_PRIORITY(2));
lo.start();
hi.start();
try
{
Thread.sleep();
}
Catch(UnInterruptedException ue)
{
System.out.println(“Trouble: “ + ue.getMessage());
}
hi.stop();
lo.stop();
System.out.println(“LOW : “ + lo.count);
System.out.println(“HIGH : “ + hi.count);
}
}
Thread Life – Cycle
suspend()
wait()
sleep()
Newly Runnable Blocked
Created
resume()
notify()
Stop() sleeptimeout
Run()
ends
Stop(0 Stop()
Run() Run()
ends ends

Dead

Figure - Life cycle of Thread

Sapna Saxena, Lecturer, Chitkara University


5
Every thread, after creation and before destruction, will always be in one of the four stages – newly
created, runnable, blocked, or dead.
 Newly created threads – A thread enters the newly created state immediately after
creation. In this state, the local data members are allocated and initialized, but execution
of the run () will not begin. After the starts () method is called, thread will be step into
Runnable state.
 Runnable – When a thread is in runnable state, the execution context exists and the thread
can be scheduled to run at any time, i.e., the thread is not waiting for any event to happen.
 Blocked – The blocked state is entered when one of the following events occurred –
o The thread itself or another thread calls the suspend() method.
o The thread calls on object’s wait() method.
o The thread is itself calls the sleep() method.
o The thread is waiting for some I/O opertion.
o The thread will join() with another thread.
A thread in a blocked state will not be scheduled for running. It will go to runnable state when the
following event occurs –
o Another thread calls resume() method.
o If the thread is blocked due to wait(), the object’s notify () or notify All ()
methods called.
o The specified sleeping time elapses.
o The specified I/O operation completed.
 Dead – The dead state is entered when a thread finishes its execution or is stopped by
another thread calling its stop() method.
Thread Groups
Every thread instance is a member of exactly one group. A thread group can have both threads and
other thread groups as its members. In fact, every thread group, except the system thread group, is a
member of some other thread group. All the threads and thread groups in an application form a tree,
with the system thread group as the root.
When a Java application is started, the JVM creates the main thread group as a member of the system
thread group. A main thread is created in the main thread group to run the main () method of the
application. By default, all new user created threads and thread group will become the members of
this main thread group unless another thread group unless another thread group is passed as the first
argument of the new statement’s constructor method.
For example,
Thread Group = new Thread Group (“New Group”);
Thread thread = new Thread )group, New Thread);
Three methods are defined in the Thread Group class to manipulate all the threads in the Thread
Class group and its sub threaded groups at once : stop (), suspend () & resume ().
Getting Information about Threads and Thread Groups
Some common methods are –
Thread Information –

Sapna Saxena, Lecturer, Chitkara University


6
currentThread () – Returns the caller’s thread
getname() – Returns the current thread name
getThreadGroup() – Returns the parent thread group of the thread
getPriority() –Returns the current priority of thread
isAlive() – Returns true if the thread is started but not dead yet
isDaemon() – Returns true if the thread is a daemon thread.
Thread Group Information –
getName() – Returns the name of thread group
getParent() – Returns the parent thread group of the thread group
getmaxPriority() – Returns the current maximum priority of the thread group
activeCount() – Returns the active thread in the thread group
activeGroupCount() – Returns the number of active thread groups in the thread group
enumerate(Thread list [], boolean recursive) – Adds all the active threads in the group
into the list array if recursive is true, all the threads in the sub threaded groups will be
copied over as well. This method will return the number of threads copied. The active
Count () method is after used to size the list when the space of this thread array is to be
allocated.
Daemon Threads
Daemon threads are service threads. They exist to provide services to other threads. They normally
enter an endless loop waiting for clients requesting services. When all the active threads remaining
are daemon threads, the Java Virtual machine will exist.
For example, a timer thread wakes up in regular intervals a good candidate for daemon threads. This
timer thread can notify other threads regularly about the timeouts.
To create a daemon thread, set Daemon () method should be called immediately after the thread’s
creation and before the execution started. By default, all the threads created by a daemon thread are
also daemon threads. The synopsis of this method is –
set Daemon (boolean isDaemon)
When is Daemon is true, the thread is marked as a daemon thread, otherwise, it is marked as a non –
daemon thread.
Thread Synchronization
Synchronization is the way to avoid data corruption caused by simultaneous access to the same data.
Because all the thread in a program share the same memory space, it is possible for two threads to
access the variable or run the same method of the same object at the same time. Problems may occur
when multiple threads are accessing the same data concurrently. Thread may race each other, and
one thread may overwrite the data just written by another thread. Or one thread may work on another
thread’s intermediate result and break the consistency of the data. Some mechanism is needed to
block one thread’s access to the critical data, if the data is being worked on by another thread.
Fortunately, the Java programming language provides several tools for controlling thread
interactions. One of the most important concepts to make effective use of Java thread is the concept
of the monitor.
A monitor is not a Java object, but each object has a monitor that can be owned by no more than one
thread at a time. Because each monitor can only be owned by zero or one thread, an object’s monitor
can be used to control how many threads have simultaneous access to a particular section of code. If

Sapna Saxena, Lecturer, Chitkara University


7
we require each thread to acquire ownership of a single monitor before executing the code, only one
thread will execute the code at the same time. This access is controlled by the synchronized keyword.
The synchronized keyword can be used like –
synchronized(anyObject)
{
//Code - -
}
Very often, whole methods need to be synchronized with respect to the this object. For these
instances, the synchronized keyword can be added to the method declaration.
The method,
public synchronized void addElement(Object obj)
{
//Code
}
is exactly the same as –
public void addElement(Object obj)
{
synchronized(this)
{
//Code
}
}
wait() and notify()
Sometimes we need one thread to wait for some event in another thread before continuing. The
java.lang.object class contains several methods that provide this functionality –
The wait () method causes the current thread to stop executing (i.e. become not schedulable) until
some other thread signal it using the notify() or notifyAll() methods. A thread must own the monitor
of the object it is waiting on. It can acquire the monitor by synchronizing on the object. If the thread
does not own the monitor when it calls wait (), an Illegal Monitor State Exception is throws. Once
the thread is blocked and waiting, it releases the monitor.
The wait () method should be used in the following way –
synchronized(obj)
{
obj.wait()
}
The wait() method can also take argument that control the amount of time the thread is willing to
suspend.
 wait(long milliseconds) – causes the thread to stop until notified or milliseconds have
elapsed, which ever comes first.
 wait(long milliseconds, int nanoseconds) – causes the thread to stop until notified or
milliseconds plus nanoseconds have elapsed whichever comes first. A thread can also exit a
wait () by being interrupted. Another thread can call interrupt() method of he waiting thread,
which causes it to receive an Interrupted Exception.
When the notify() method of an object is called, one of the threads waiting on the object is
awakened. If more than one thread is waiting, then one is picked in a manner that is implementation
Sapna Saxena, Lecturer, Chitkara University
8
– dependent. That is, each vendor is free to implement a different scheme for waking up waiting
threads.
In contrast, notify All () wakes up all waiting threads. As with wait (), the thread calling notify () or
notify All () must own the monitor for the object being notified. Because the thread blocked on the
wait () owned the monitor when they started waiting, after they are notified, they must require the
monitor before continuing.

Sapna Saxena, Lecturer, Chitkara University

You might also like