0% found this document useful (0 votes)
72 views22 pages

Unit - Iv 4.1 Multithreading Programming

This document discusses multithreading in Java. It defines multithreading as a program containing multiple concurrent threads, with each thread defining a separate path of execution. It notes that Java provides built-in support for multithreading and describes the differences between multithreading and multitasking. The document also outlines the Java thread lifecycle and states, and describes two ways to create threads in Java: using the predefined Thread class or implementing the Runnable interface.

Uploaded by

Meena Murugesan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
72 views22 pages

Unit - Iv 4.1 Multithreading Programming

This document discusses multithreading in Java. It defines multithreading as a program containing multiple concurrent threads, with each thread defining a separate path of execution. It notes that Java provides built-in support for multithreading and describes the differences between multithreading and multitasking. The document also outlines the Java thread lifecycle and states, and describes two ways to create threads in Java: using the predefined Thread class or implementing the Runnable interface.

Uploaded by

Meena Murugesan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 22

UNIT – IV

4.1 MULTITHREADING PROGRAMMING:


 Java provides built-in support for multithreaded programming.
 Multithreaded program contains two or more parts that can run concurrently. Each part of
such a program is called a thread, and each thread defines a separate path of execution.
 Multithreading is a specialized form of multitasking
 Multitasking are of two types:
Process-Based Multitasking: Allows computer to run two or more programs concurrently.
A program is the smallest unit of code that can be dispatched by the scheduler.
Thread-Based Multitasking: Single program can perform two or more tasks
simultaneously. The thread is the smallest unit of dispatchable code.
4.2 DIFFERENCES BETWEEN MULTI-THREADING AND MULTITASKING:

Multithreading Multitasking

Light weight process share the same address Heavy weight process that requires their own
space separate address space
Less Overhead High Overhead
Inter-Thread communication is in-expensive Inter-Process Communication is expensive
Context switching from one thread to the next Context switching from one process to another
is low cost is costly.

 Multithreading enables to write efficient programs that make a maximum use of the CPU,
because idle time can be kept to a minimum.
 Ex: Local File system resources are read and written at a much slower than they can be
processed by the CPU.
 In a traditional single-threaded environment, program has to wait for each of these tasks
to finish before it can proceed to the next one, even though the CPU is sitting idle most of
the time.
4.3 THE JAVA THREAD LIFE CYCLE:
 Java uses threads to enable the entire environment to be asynchronous.
 This helps reduce inefficiency by preventing the waste of CPU cycles.
 The single-threaded systems use an approach called an event loop with polling.
 A single thread of control runs in an infinite loop, polling a single event queue to decide
what to do next.
 Polling mechanisms returns saying that a network file is ready to be read, then the event
loop dispatches control to the appropriate event handler.
 Until this event handler returns, nothing else can happen in the system. This waste CPU
time.
Results in one part of a program dominating the system and preventing any other events
from being processed.
In the single-threaded environment, when a thread blocks, because it is waiting for some
resource, the entire program stops running.
 In java’s multithreading, the loop/polling mechanism is eliminated. One thread can pause
without stopping other parts of your program,
 Ex: Idle time created when a thread reads data from a network or waits for user input can
be utilized elsewhere.
 When a thread blocks, in a java program, only the single thread that is blocked pauses all
other threads continue to run.
 Threads exist in several states: A thread can be running. It can be ready to run as soon as
it gets CPU time.
o A running thread can be suspended, which temporarily suspends its activity.
o A suspended thread can then be resumed, allowing it to pick up where it left off.
o A thread can be blocked when waiting for a resource.
o At anytime, a thread can be terminated, which halts its execution immediately.
Once terminated, a thread cannot be resumed.

4.3.1 Thread priorities:


 Java assigns to each thread a priority that determines how that thread should be treated
with respect to the others.
 Thread priorities are integers that specify the relative priority of one thread to another.
 Thread priority is used to decide when to switch from one running thread to the next.
This is called a context switch.
 The rules that determine when a context switch takes place are simple:
i) A thread can voluntarily relinquish control: This is done by explicitly yielding,
sleeping, or blocking on pending I/O. The highest-priority thread that is ready to
ii) run is given the CPU.
i) A thread can be preempted by a higher-priority thread: Lower-priority thread that
does not yield the processor is simply preempted by a higher-priority thread. This
is called preemptive multitasking.

4.3.2 Synchronization:
 If any two threads to communicate and share a complicated data structure, such as a
linked list, There should be some way to ensure that they don’t conflict with each other.
(i.e.. when one thread is reading, we have to prevent another thread from waiting data to
it.)
 Java implements a model of interprocess synchronization: the monitor.
 Monitor is a control mechanism, it is viewed as a very small box that can hold only one
thread. Once a thread enters a monitor, all other threads must wait until that thread exits
the monitor.
 In Java, each object has its own implicit monitor that is automatically entered when one
of the object’s synchronized methods is called. Once a thread is inside a synchronized
method, no other thread can call any other synchronized method on the same object.

4.4 CREATING THREADS:


 Two basic ways of creating threads
i) Using predefined thread class
ii) Using runnable interface
 The thread class defines several methods that help manage threads.
Method Meaning
getName Obtain a thread’s name
getpriority Obtain a thread’s priority
isAlive Determine if a thread is still running
Join Wait for a thread to terminate
Run Entry point for the thread
Sleep Suspend a thread for a period of time
Start Start a thread by calling its run method

4.4.1 The Main Thread:


 When a java program starts up, one thread begins running immediately. This is usually
called the main thread of program, because it is the one that is executed when program
begins.
 The main thread is important for two reasons:
It is the thread from which other “child” threads will be spawned
Often, it must be the last thread to finish execution because it performs various shutdown
actions.
 The main thread is created automatically when program is started, but it has to be
controlled through a thread object.
 Reference is created by calling the method currentThread() which is a static member of
thread.
 This method returns a reference to the thread in which it is called.
class CurrentThreadDemo {
public static void main(String args[]) {
Thread t = Thread.currentThread();
System.out.println("Current thread: " + t);
// change the name of the thread
t.setName("My Thread");
System.out.println("After name change: " + t);
try {
for(int n = 5; n > 0; n--) {
System.out.println(n);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted");
}
}
}
 Reference to the current thread is obtained by using currentThread().
 Next the program displays information about the thread.
 Calls setName() to change the internal name of the thread.
 Next, a loop counts down from five, pausing one second in between each line. Pausing is
accomplished by the sleep() method.
 The argument to sleep() specifies the delay period in milliseconds.
 The sleep() method in Thread might throw InterruptedException happens if some other
thread wanted to interrupt this sleeping one. It prints the message.
Current thread: Thread[main,5,main]
After name change: Thread[My Thread,5,main]
5
4
3
2
1
Methods defined by Thread:

1) static void sleep(long milliseconds) throws InterruptedException


The number of milliseconds to suspend is specified in milliseconds. This method may
throw an InterruptedException.

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


This second form is useful only in environments that allow timing periods as short as
nanoseconds.

3) final void setName(String threadName)


set the name of a thread by using setName
4) final String getName( )
obtains the name of a thread.

4.4.2 Creating a thread-implementing runnable interface:


 The easiest way to create a thread is to create a class that implements the Runnable
interface.
 To implement Runnable, a class need only implement a single method called run( ),
which is declared like this:
public void run( )
 After the new thread is created, it will not start running until we call its start( ) method
void start( )
Ex: class NewThread implements Runnable
{
Thread t;
NewThread( )
{
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start();
}
public void run( )
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
}
catch (InterruptedException e)
{
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ThreadDemo
{
public static void main(String args[ ])
{
new NewThread( ); // create a new thread
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
 Inside NewThread’s constructor, a new Thread object is created.
 Next start( ) method is called, which starts the thread of execution beginning at the run( )
method. This causes the child thread’s for loop to begin.
 After calling start( ), NewThread’s constructor returns to main( ).
 When the main thread resumes, it enters its for loop.
 Both threads continue running, sharing the CPU, until their loops finish.
Output: Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
 In a multithreaded program, often the main thread must be the last thread to finish
running.
4.4.3 Extending thread:
 The second way to create a thread is to create a new class that extends thread, and then to
create an instance of that class.
Ex: class NewThread extends Thread
{
NewThread( )
{
super("Demo Thread");
System.out.println("Child thread: " + this);
start( );
}
public void run( )
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
}
catch (InterruptedException e)
{
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ExtendThread
{
public static void main(String args[ ])
{
new NewThread();
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
Output is same as the above

4.4.3 Creating multiple threads:


The following program creates three child threads.
Ex: class NewThread implements Runnable
{
String name;
Thread t;
NewThread(String threadname)
{
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start( );
}
public void run( )
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
}
System.out.println(name + " exiting.");
}
}
class MultiThreadDemo
{
public static void main(String args[ ])
{
new NewThread("One");
new NewThread("Two");
new NewThread("Three");
try
{
Thread.sleep(10000);
}
catch (InterruptedException e)
{
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Output: New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
New thread: Thread[Three,5,main]
One: 5
Two: 5
Three: 5
One: 4
Two: 4
Three: 4
One: 3
Three: 3
Two: 3
One: 2
Three: 2
Two: 2
One: 1
Three: 1
Two: 1
One exiting.
Two exiting.
Three exiting.
Main thread exiting.

4.4.4. Using isAlive( ) and join( ):


 The main thread must be the last thread to finish. This is accomplished by calling sleep( )
within main( ). With a long enough delay to ensure that all child threads terminate prior
to the main thread.
 But it is not a satisfactory solution. One thread does not know when another thread has
ended.
 Two ways exist to determine whether a thread has finished
i) isAlive( ) => final boolean isAlive( )
= true if the thread is still running
= false otherwise
ii) join( ) => final void join( ) throws Interrupted exception
= waits until the thread on which it is called terminates
Ex: class NewThread implements Runnable
{
String name;
Thread t;
NewThread(String threadname)
{
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start( );
}
public void run( )
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
}
class DemoJoin
{
public static void main(String args[ ])
{
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
NewThread ob3 = new NewThread("Three");
System.out.println("Thread One is alive: "+ ob1.t.isAlive());
System.out.println("Thread Two is alive: "+ ob2.t.isAlive());
System.out.println("Thread Three is alive: "+ ob3.t.isAlive());
try
{
System.out.println("Waiting for threads to finish.");
ob1.t.join( );
ob2.t.join( );
ob3.t.join( );
}
catch (InterruptedException e)
{
System.out.println("Main thread Interrupted");
}
System.out.println("Thread One is alive: "+ ob1.t.isAlive());
System.out.println("Thread Two is alive: "+ ob2.t.isAlive());
System.out.println("Thread Three is alive: "+ ob3.t.isAlive());
System.out.println("Main thread exiting.");
}
}
Output: New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
New thread: Thread[Three,5,main]
Thread One is alive: true
Thread Two is alive: true
Thread Three is alive: true
Waiting for threads to finish.
One: 5
Two: 5
Three: 5
One: 4
Two: 4
Three: 4
One: 3
Two: 3
Three: 3
One: 2
Two: 2
Three: 2
One: 1
Two: 1
Three: 1
Two exiting.
Three exiting.
One exiting.
Thread One is alive: false
Thread Two is alive: false
Thread Three is alive: false
Main thread exiting.
4.4.5 Thread priorities:
 Can set priorities to the threads.
 To set a thread’s priority, use the setPriority ( ) method, which is a member of thread.
 General form: final void setPriority (int level)
 The value of level must be within the range
MIN_PRIORITY and MAX_PRIORITY
 Default priority is NORM_PRIORITY
 We can obtain the current priority setting by calling the getPriority( ) method.
final int getPriority( )
class th extends Thread
{
public void run( )
{
for(int i=0; i<5; i++)
{
System.out.println(“Thread”);
}
}
}
class t2 extends Thread
{
public void run( )
{
System.out.println(“t2”);
}
}
class t3 extends Thread
{
public void run( )
{
System.out.println(“t3”);
}
}
class demo
{
public static void main(String args[ ])
{
th t = new th( );
t.setPriority(Thread.MIN_PRIORITY);
t.start( );
t2 tx = new t2( );
tx.setPriority(Thread.MAX_PRIORITY);
tx.start( );
t3 ty = new t3( );
ty.setPriority(Thread.NORM_PRIORITY);
ty.start( );
}
}

4.5 USING SYNCHRONIZED METHODS:


 Synchronization is easy in Java, because all objects have their own implicit monitor
associated with them.
 To enter an object’s monitor, just call a method that has been modified with the
synchronized keyword.
 While a thread is inside a synchronized method, all other threads that try to call it (or any
other synchronized method) on the same instance have to wait.
 To exit the monitor and relinquish control of the object to the next waiting thread, the
owner of the monitor simply returns from the synchronized method.
Ex: class Callme
{
void call(String msg)
{
System.out.print("[" + msg);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable
{
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s)
{
target = targ;
msg = s;
t = new Thread(this);
t.start( );
}
public void run( )
{
target.call(msg);
}
}

class Synch
{
public static void main(String args[ ])
{
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
try
{
ob1.t.join( );
ob2.t.join( );
ob3.t.join( );
}
catch(InterruptedException e)
{
System.out.println("Interrupted");
}
}
}
Output: Hello [Synchronized [World]
]
]
 By calling sleep( ), the call( ) method allows execution to switch to another thread.
 This results in the mixed-up output of the three message strings.
 In this program, nothing exists to stop all three threads from calling the same method, on
the same object, at the same time. This is known as a race condition, because the three
threads are racing each other to complete the method.
 We must serialize access to call( ). That is restrict its access to only one thread at a time.
 To do this, simply need to precede call( )’s definition with the keyword synchronized.
synchronized void call(String msg)
{
...
This prevents other threads from entering call( ) while another thread is using it.

The output of the program is as follows:


[Hello]
[Synchronized]
[World]

4.6 INTER-THREAD COMMUNICATION:


To avoid polling, Java includes inter process communication mechanism via the wait(),
notigy(), notifyAll() methods.
These methods are implemented as final methods in Object.
wait( ) tells the calling thread to give up the monitor and go to sleep until some
other thread enters the same monitor and calls notify( ).
• notify( ) wakes up a thread that called wait( ) on the same object.
• notifyAll( ) wakes up all the threads that called wait( ) on the same object. One of
the threads will be granted access
These methods are declared within Object, as shown here:
final void wait( ) throws InterruptedException
final void notify( )
final void notifyAll( )
It consists of four classes: Q, the queue that you’re trying to synchronize; Producer, the
threaded object that is producing queue entries; Consumer, the threaded object that is
consuming queue entries; and PC, the tiny class that creates the single Q,Producer, and
Consumer.

class Q {
int n;
synchronized int get() {
System.out.println("Got: " + n);
return n;
}
synchronized void put(int n) {
this.n = n;
System.out.println("Put: " + n);
}
}

class Producer implements Runnable {


Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while(true) {
q.put(i++);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while(true) {
q.get();
}
}
}
class PC {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}
Although synchronized, nothing stops the producer from over running the consumer, nor will
anything stop the consumer from consuming the same queue value twice.
The proper way is to write this program is to use wait(), notify()
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
while(!valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
while(valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}

4.7 DAEMON THREAD:


Daemon thread is a low priority thread that runs in background to perfrom tasks such as garbage
collection etc.
Daemon thread do not prevent the JVM from exiting when all the user threads finish their
execution.
JVM terminates itself when all user threads finish their execution.
Properties:
Newly created threads are non-daemon threads by default. However user thread can be made as
daemon by using setDaemon() method of Thread class.
Methods of Thread class that are related to Daemon threads:
i) public void setDaemon(boolean status)
Ex: User defined thread t would be set to daemon by using t.setDaemon(true)
ii) public boolean isDaemon()
Check the status of the thread. It returns true if the thread is daemon, else it returns
false.
setDaemon() method can only be called before starting the thread. This method will throw
IllegalThreadStateException if it is called after Thread start().

public class DaemonThreadExample1 extends Thread{


public void run(){

// Checking whether the thread is Daemon or not


if(Thread.currentThread().isDaemon()){
System.out.println("Daemon thread executing");
}
else{
System.out.println("user(normal) thread executing");
}
}
public static void main(String[] args){
/* Creating two threads: by default they are
* user threads (non-daemon threads)
*/
DaemonThreadExample1 t1=new DaemonThreadExample1();
DaemonThreadExample1 t2=new DaemonThreadExample1();

//Making user thread t1 to Daemon


t1.setDaemon(true);

//starting both the threads


t1.start();
t2.start();
}
}
Output:

Daemon thread executing


user(normal) thread executing

4.8 THREADGROUPS:
Thread groups is a way to manage groups of threads as a unit. This is useful when want to
suspend and resume a number of related threads.
Constructor
ThreadGroup(String name) – creates a thread group with given name
ThreadGroup(ThreadGroup parent, String name) – creates a thread group with the given parent
group and name.
public class ThreadGroupDemo implements Runnable
{
public void run()
{
System.out.println(Thread.currentThread().getName());
}
public static void main(String args[])
{
ThreadGroupDemo runnable = new ThreadGroupDemo();
ThreadGroup tg1 = new ThreadGroup(“Parent Thread Group”);
Thread t1 = new Thread(tg1, runnable, “one”);
t1.start();
Thread t2 = new Thread(tg1, runnable, “two”);
t2.start();
}
}

4.9 GENERIC PROGRAMMING

Generics are parameterized types.

It enables to create classes , interfaces and methods in which the type of data upon which they
operate is specified as a parameter.

Using generics, it is possible to create single class that automatically works with different types
of data.

Java has the ability to create generalized classes, interfaces and methods by operating through
references of type Object. It can refer to any type of object.

4.9.1 Generic classes:

class Gen<T> {
T ob; // declare an object of type T
// Pass the constructor a reference to
// an object of type T.
Gen(T o) {
ob = o;
}
// Return ob.
T getob() {
return ob;
}
// Show type of T.
void showType() {
System.out.println("Type of T is " +
ob.getClass().getName());
}
}

class GenDemo {
public static void main(String args[]) {
// Create a Gen reference for Integers.
Gen<Integer> iOb;
// Create a Gen<Integer> object and assign its
// reference to iOb. Notice the use of autoboxing
// to encapsulate the value 88 within an Integer object.
iOb = new Gen<Integer>(88);
// Show the type of data used by iOb.
iOb.showType();
// Get the value in iOb. Notice that
// no cast is needed.
int v = iOb.getob();
System.out.println("value: " + v);
System.out.println();
// Create a Gen object for Strings.
Gen<String> strOb = new Gen<String>("Generics Test");
// Show the type of data used by strOb.
strOb.showType();
// Get the value of strOb. Again, notice
// that no cast is needed.
String str = strOb.getob();
System.out.println("value: " + str);
}
}
The output produced by the program is shown here:
Type of T is java.lang.Integer
value: 88
Type of T is java.lang.String
value: Generics Test

T is the name of a type parameter. This name is used as a place holder for the actual type that
will be passed to Gen when an object is created.

4..9.2 Generic Methods:

Single generic method declaration that can be called with arguments of different types.

Based on the types of the arguments passed to the generic method, the compiler handles each
method call appropriately.
public class GenericMethodTest
{
public static <T> void printArray(T[] inputArray)
{
for(T element: inputArray)
{ System.out.printf(“%s”, element); }
}
public static void main(String args[])
{
Integer[] intArray = {1,2,3,4,5};
Double[] doubleArray = [1.1,2.2,3.3,4.4,5.5};
System.out.println(“Array contains”);
printArray(intArray);
printArray(doubleArray);
}
}
4.9.3 Bounded Types:

Restrict the kinds of types that are allowed to be passed to a type parameter.

Ex: a method that operates on numbers might want to accept instances of Number or its
subclasses.

To declare a bounded type parameter, list the type parameters’ name, followed by the extends
keyword, followed by its upper bound.

public class GenericClass<T extends Number>


{
T t;
public Genericclass(T t)
{
this.t = t; }
public T get()
{
return t;
}
}
public class GenericData
{
public static void main()
{
GenericClass <Number> g1 = new GenericClass <Number>(123);
GenericClass <Integer> g2 = new GenericClass <Integer>(456);
}
}

4.9.3 Restrictions and Limitations:

There are a few restrictions when using generics:

i) Type parameters cannot be instantiated.


T ob = new T();
Compiler does not know the type of object to create.
ii) Generic Array restrictions
T vals[] = new T[10] // illegal cannot create an array of T
Gen <Integer> gens[] = new Gen <Integer>[10] //Illegal cant create type-specific
generic references.
Gen <?> gens[] = new Gen <?> [10] //ok
iii) Generic Exceptions Restrctions
A generic class cannot create Throwable. This means that you cannot create generic
exception classes.

You might also like