5thmodule1 Enum1 Merged
5thmodule1 Enum1 Merged
UNIT-5
1
Comparison between multithreading and multi-tasking
Parameter Multi Tasking Multi Threading
Basic Multitasking lets CPU to execute Multithreading lets CPU to execute
multiple tasks at the same time. multiple threads of a process simul-
taneously.
Switching In multitasking, CPU switches In multithreading, CPU switches
between programs frequently. between the threads frequently.
Memory and In multitasking, system has to In multithreading, system has to
Resource allocate separate memory and allocate memory to a process,
resources to each program that multiple threads of that process shares
CPU is executing. the same memory and resources
allocated to the process.
Multitasking
Multitasking is when a single CPU performs several tasks (program, process, task,
threads) at the same time. To perform multitasking, the CPU switches among these tasks very
frequently so that user can interact with each program simultaneously.
In a multitasking operating system, several users can share the system simultaneously.
CPU rapidly switches among the tasks, so a little time is needed to switch from one user to the
next user. This puts an impression on a user that entire computer system is dedicated to him.
Figure: Multitasking
When several users are sharing a multitasking operating system, CPU scheduling and
multiprogramming makes it possible for each user to have at least a small portion of
Multitasking OS and let each user have at least one program in the memory for execution.
2
Multi threading
Multithreading is different from multitasking in a sense that multitasking allows mul- tiple
tasks at the same time, whereas, the Multithreading allows multiple threads of a single task
(program, process) to be processed by CPU at the same time.
A thread is a basic execution unit which has its own program counter, set of the register
and stack. But it shares the code, data, and file of the process to which it belongs. A process
can have multiple threads simultaneously, and the CPU switches among these threads so fre-
quently making an impression on the user that all threads are running simultaneously.
Figure: Multithreading
Benefits of Multithreading
application is not responding, the other would respond in that sense the user would
not have to sit idle.
• Multithreading allows resource sharing as threads belonging to the same process can
share code and data of the process and it allows a process to have multiple threads at
the same time active in same address space.
• Creating a different process is costlier as the system has to allocate different memory
and resources to each process, but creating threads is easy as it does not require
allocating separate memory and resources for threads of the same process.
4.2 THREAD LIFECYCLE
A thread in Java at any point of time exists in any one of the following states. A thread lies
only in one of the shown states at any instant:
3
1) New
2) Runnable
3) Blocked
4) Waiting
5) Timed Waiting
6) Terminated
The following figure represents various states of a thread at any instant of time:
4
• It is the responsibility of the thread scheduler to give the thread, time to run.
• A multi-threaded program allocates a fixed amount of time to each individual thread.
Each and every thread runs for a short while and then pauses and relinquishes the CPU
to another thread, so that other threads can get a chance to run. When this happens,
all such threads that are ready to run, waiting for the CPU and the currently running
thread lies in runnable state.
3. Blocked/Waiting state:
• When a thread is temporarily inactive, then it’s in one of the following states:
○ Blocked
○ Waiting
• For example, when a thread is waiting for I/O to complete, it lies in the blocked state.
It’s the responsibility of the thread scheduler to reactivate and schedule a blocked/
waiting thread.
• A thread in this state cannot continue its execution any further until it is moved to
runnable state. Any thread in these states do not consume any CPU cycle.
• A thread is in the blocked state when it tries to access a protected section of code that
is currently locked by some other thread. When the protected section is unlocked, the
schedule picks one of the threads which is blocked for that section and moves it to the
runnable state. A thread is in the waiting state when it waits for another thread ona
condition. When this condition is fulfilled, the scheduler is notified and the waiting
thread is moved to runnable state.
• If a currently running thread is moved to blocked/waiting state, another thread in the
runnable state is scheduled by the thread scheduler to run. It is the responsibility of
thread scheduler to determine which thread to run.
4. Timed Waiting:
• A thread lies in timed waiting state when it calls a method with a time out parameter.
• A thread lies in this state until the timeout is completed or until a notification is
received.
• For example, when a thread calls sleep or a conditional wait, it is moved to timed
waiting state.
5. Terminated State:
• A thread terminates because of either of the following reasons:
○ Because it exits normally. This happens when the code of thread has entirely
executed by the program.
5
○ Because there occurred some unusual erroneous event, like segmentation fault
or an unhandled exception.
• A thread that lies in terminated state does no longer consumes any cycles of CPU.
Creating Threads
• Threading is a facility to allow multiple tasks to run concurrently within a single
process. Threads are independent, concurrent execution through a program, and each
thread has its own stack.
In Java, There are two ways to create a thread:
1) By extending Thread class.
2) By implementing Runnable interface.
Java Thread Benefits
1. Java Threads are lightweight compared to processes as they take less time and re-
source to create a thread.
2. Threads share their parent process data and code
3. Context switching between threads is usually less expensive than between process-
es.
4. Thread intercommunication is relatively easy than process communication.
Thread class:
Thread class provide constructors and methods to create and perform operations on a
thread. Thread class extends Object class and implements Runnable interface.
Commonly used Constructors of Thread class:
• Thread()
• Thread(String name)
• Thread(Runnable r)
• Thread(Runnable r, String name)
Commonly used methods of Thread class:
1. public void run(): is used to perform action for a thread.
2. public void start(): starts the execution of the thread. JVM calls the run() method on
the thread.
3. public void sleep(long miliseconds): Causes the currently executing thread to sleep
(temporarily cease execution) for the specified number of milliseconds.
4. public void join(): waits for a thread to die.
6
5. public void join(long miliseconds): waits for a thread to die for the specified mili-
seconds.
6. public int getPriority(): returns the priority of the thread.
7. public int setPriority(int priority): changes the priority of the thread.
8. public String getName(): returns the name of the thread.
9. public void setName(String name): changes the name of the thread.
10. public Thread currentThread(): returns the reference of currently executing
thread.
7
Extending Thread
The first way to create a thread is to create a new class that extends Thread, and then to
create an instance of that class. The extending class must override the run( ) method, which
is the entry point for the new thread. It must also call start( ) to begin execution of the new
thread.
Sample java program that creates a new thread by extending Thread:
// Create a second thread by extending Thread
class NewThread extends Thread
{
NewThread()
{ // Create a new, second thread
super(“Demo Thread”);
System.out.println(“Child thread: “ + this);
start(); // Start the thread
}
// This is the entry point for the second thread.
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(“Child thread is exiting”);
8
}
}
public class ExtendThread
{
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 is exiting.”);
}
}
Sample Output:
(output may vary based on processor speed and task load)
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
9
Child Thread: 2
Main Thread: 3
Child Thread: 1
Child thread is exiting.
Main Thread: 2
Main Thread: 1
Main thread is exiting.
The child thread is created by instantiating an object of NewThread, which is derived from
Thread. The call to super( ) is inside NewThread. This invokes the following form of the
Thread constructor:
public Thread(String threadName)
Here, threadName specifies the name of the thread.
Implementing Runnable
• The easiest way to create a thread is to create a class that implements the Runnable
interface.
• Runnable abstracts a unit of executable code. We can construct a thread on any object
that implements Runnable.
• To implement Runnable, a class need only implement a single method called run( ),
which is declared as:
public void run( )
• Inside run( ), we will define the code that constitutes the new thread. The run( )
can call other methods, use other classes, and declare variables, just like the main
thread can. The only difference is that run( ) establishes the entry point for another,
concurrent thread of execution within the program. This thread will end when run( )
returns.
• After we create a class that implements Runnable, we will instantiate an object of
type Thread from within that class.
• After the new thread is created, it will not start running until we call its start( ) method,
which is declared within Thread. In essence, start( ) executes a call to run( ).
• The start( ) method is shown as:
void start( )
10
Sample java program that creates a new thread by implementing Runnable:
// Create a second thread
class NewThread implements Runnable
{
Thread t;
NewThread()
{
// Create a new, second thread
t = new Thread(this, “Demo Thread”);
System.out.println(“Child thread: “ + t);
t.start(); // Start the thread
}
// This is the entry point for the second thread.
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(“Child thread is exiting.”);
}
}
11
public 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 is exiting.”);
}
}
Inside NewThread’s constructor, a new Thread object is created by the following
statement:
t = new Thread(this, “Demo Thread”);
Passing this as the first argument indicates that we want the new thread to call the run( )
method on this object. Next, start( ) 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.
12
Sample Output:
(output may vary based on processor speed and task load)
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
Child thread is exiting.
Main Thread: 2
Main Thread: 1
Main thread is exiting.
In a multithreaded program, often the main thread must be the last thread to finish run-
ning. In fact, for some older JVMs, if the main thread finishes before a child thread has
completed, then the Java run-time system may “hang.” The preceding program ensures that
the main thread finishes last, because the main thread sleeps for 1,000 milliseconds between
iterations, but the child thread sleeps for only 500 milliseconds. This causes the child thread
to terminate earlier than the main thread.
Choosing an Approach
The Thread class defines several methods that can be overridden by a derived class. Of
these methods, the only one that must be overridden is run(). This is, of course, the same
method required when we implement Runnable. Many Java programmers feel that classes
should be extended only when they are being enhanced or modified in some way. So, if we
will not be overriding any of Thread’s other methods, it is probably best simply to implement
Runnable.
13
Creating Multiple Threads
The following program creates three child threads:
// Create multiple threads.
class NewThread implements Runnable
{
String name; // name of thread
Thread t;
NewThread(String threadname)
{
name = threadname;
t = new Thread(this, name);
System.out.println(“New thread: “ + t);
t.start(); // Start the thread
}
// This is the entry point for thread.
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.”);
14
}
}
public class MultiThreadDemo
{
public static void main(String args[])
{
new NewThread(“One”); // start threads
new NewThread(“Two”);
new NewThread(“Three”);
try
{
// wait for other threads to end
Thread.sleep(10000);
}
catch (InterruptedException e)
{
System.out.println(“Main thread Interrupted”);
}
System.out.println(“Main thread exiting.”);
}
}
The output from this program is shown here:
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
15
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.
As we can see, once started, all three child threads share the CPU. The call to sleep(10000)
in main(). This causes the main thread to sleep for ten seconds and ensures that it will finish
last.
Using isAlive( ) and join( )
We want the main thread to finish last. In the preceding examples, 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. However, this is hardly a satisfactory solution, and it also
raises a larger question: How can one thread know when another thread has ended?
Two ways exist to determine whether a thread has finished or not.
• First, we can call isAlive( ) on the thread. This method is defined by Thread.
Syntax:
final boolean isAlive( )
The isAlive( ) method returns true, if the thread upon which it is called is still running. It
returns false, otherwise.
• Second, we can use join() to wait for a thread to finish.
Syntax:
final void join( ) throws InterruptedException
16
This method waits until the thread on which it is called terminates. Its name comes from
the concept of the calling thread waiting until the specified thread joins it.
Sample Java program using join() to wait for threads to finish.
class NewThread implements Runnable
{
String name; // name of thread
Thread t;
NewThread(String threadname)
{
name = threadname;
t = new Thread(this, name);
System.out.println(“New thread: “ + t);
t.start(); // Start the thread
}
// This is the entry point for thread.
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 + “ is exiting.”);
17
}
}
public 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());
// wait for threads to finish
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 is exiting.”);
}
}
18
Sample output:
(output may vary based on processor speed and task load)
New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
One: 5
New thread: Thread[Three,5,main]
Two: 5
Thread One is alive: true
Thread Two is alive: true
Thread Three is alive: true
Waiting for threads to finish.
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
One is exiting.
Two is exiting.
Three is exiting.
Thread One is alive: false
Thread Two is alive: false
Thread Three is alive: false
Main thread is exiting.
19
As we can see, after the calls to join( ) return, the threads have stopped executing.
4.3 SYNCHRONIZATION
• Synchronization in java is the capability to control the access of multiple threads to
any shared resource.
• Java Synchronization is better option where we want to allow only one thread to
access the shared resource.
• When two or more threads need access to a shared resource, they need some way to
ensure that the resource will be used by only one thread at a time. The process by
which this is achieved is called synchronization. Java provides unique, language-
level support for it.
• Key to synchronization is the concept of the monitor (also called a semaphore).
• A monitor is an object that is used as a mutually exclusive lock, or mutex. Only one
thread can own a monitor at a given time. When a thread acquires a lock, it is said
to have entered the monitor. All other threads attempting to enter the locked monitor
will be suspended until the first thread exits the monitor.
• These other threads are said to be waiting for the monitor. A thread that owns a monitor
can reenter the same monitor if it so desires.
• Approaches:
○ Using synchronized Method
○ Using synchronized Statement
Using Synchronized Methods
Synchronization is easy in Java, because all objects have their own implicit monitor as-
sociated with them.
To enter an object’s monitor, just call a method that has been modified with the synchro-
nized 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.
• To understand the need for synchronization, we will consider a simple example that
does not use it—but should.
• The following program has three simple classes.
• The first one, Callme, has a single method named call( ). The call( ) method takes a
String parameter called msg. This method tries to print the msg string inside of square
brackets. After call( ) prints the opening bracket and the msg string, it calls Thread.
20
sleep(1000), which pauses the current thread for one second.
• The constructor of the next class, Caller, takes a reference to an instance of the Callme
class and a String, which are stored in target and msg, respectively. The constructor
also creates a new thread that will call this object’s run( ) method. The thread is started
immediately. The run( ) method of Caller calls the call( ) method on the targetinstance
of Callme, passing in the msg string.
• Finally, the Synch class starts by creating a single instance of Callme, and three
instances of Caller, each with a unique message string.
• The same instance of Callme is passed to each Caller.
// This program is not synchronized.
class Callme
{
void call(String msg)
{
System.out.print(“[“ + msg);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println(“Interrupted”);
}
System.out.println(“]”);
}
}
21
Thread t;
public Caller(Callme targ, String s)
{
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
public void run()
{
target.call(msg);
}
}
22
{
System.out.println(“Interrupted”);
}
}
}
Sample Output:
Hello[Synchronized[World]
]
]
As we can see, 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.
This example used sleep( ) to make the effects repeatable and obvious. In most situations,
a race condition is more subtle and less predictable, because we can’t be sure when the con-
text switch will occur. This can cause a program to run right one time and wrong the next.
To fix the preceding program, we must serialize access to call(). That is, we must restrict
its access to only one thread at a time. To do this, we simply need to precede call()’s definition
with the keyword synchronized, as shown here:
This prevents other threads from entering call( ) while another thread is using it.
class Callme
{
synchronized void call(String msg)
{
...
Following is the sample java program after synchronized has been added to call( ):
class Callme
{
synchronized void call(String msg)
{
System.out.print(“[“ + msg);
23
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println(“Interrupted”);
}
System.out.println(“]”);
}
}
24
public 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”);
// wait for threads to end
try
{
ob1.t.join();
ob2.t.join();
ob3.t.join();
}
catch(InterruptedException e)
{
System.out.println(“Interrupted”);
}
}
}
Output:
[Hello]
[Synchronized]
[World]
Using synchronized Statement
While creating synchronized methods within classes that we create is an easy and effec-
tive means of achieving synchronization, it will not work in all cases. We have to put calls to
the methods defined by the class inside a synchronized block.
Syntax:
25
synchronized(object)
{
// statements to be synchronized
}
Here, object is a reference to the object being synchronized. A synchronized block en-
sures that a call to a method that is a member of object occurs only after the current thread has
successfully entered object’s monitor.
Here is an alternative version of the preceding example, using a synchronized block with-
in the run( ) method:
// This program uses a synchronized block.
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;
26
public Caller(Callme targ, String s)
{
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
// synchronize calls to call()
public void run()
{
synchronized(target)
{
// synchronized block
target.call(msg);
}
}
}
public class Synch1
{
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”);
// wait for threads to end
try
{
ob1.t.join();
ob2.t.join();
27
ob3.t.join();
}
catch(InterruptedException e)
{
System.out.println(“Interrupted”);
}
}
}
Here, the call( ) method is not modified by synchronized. Instead, the synchronized state-
ment is used inside Caller’s run( ) method. This causes the same correct output as the preced-
ing example, because each thread waits for the prior one to finish before proceeding.
Sample Output:
[Hello]
[World]
[Synchronized]
Priority of a Thread (Thread Priority):
Each thread has a priority. Priorities are represented by a number between 1 and 10. In
most cases, thread schedular schedules the threads according to their priority (known as pre-
emptive scheduling). But it is not guaranteed because it depends on JVM specification that
which scheduling it chooses.
3 constants defined in Thread class:
1. public static int MIN_PRIORITY
28
System.out.println(“running thread name is:”+Thread.currentThread().getName());
System.out.println(“running thread priority is:”+Thread.currentThread().getPriority());
}
public static void main(String args[])
{
TestMultiPriority1 m1=new TestMultiPriority1();
TestMultiPriority1 m2=new TestMultiPriority1();
m1.setPriority(Thread.MIN_PRIORITY);
m2.setPriority(Thread.MAX_PRIORITY);
m1.start();
m2.start();
}
}
Output:
running thread name is:Thread-0
running thread priority is:10
running thread name is:Thread-1
running thread priority is:1
4.4 INTER-THREAD COMMUNICATION
Inter-process communication (IPC) is a mechanism that allows the exchange of data be-
tween processes. By providing a user with a set of programming interfaces, IPC helps a
programmer organize the activities among different processes. IPC allows one application to
control another application, thereby enabling data sharing without interference.
IPC enables data communication by allowing processes to use segments, semaphores, and
other methods to share memory and information. IPC facilitates efficient message transfer
between processes. The idea of IPC is based on Task Control Architecture (TCA). It is a flex- ible
technique that can send and receive variable length arrays, data structures, and lists. It has the
capability of using publish/subscribe and client/server data-transfer paradigms while
supporting a wide range of operating systems and languages.
Inter-thread communication or Co-operation is all about allowing synchronized threads to
communicate with each other. Interthread communication is important when you develop an
application where two or more threads exchange some information.
29
Cooperation (Inter-thread communication) is a mechanism in which a thread is paused
running in its critical section and another thread is allowed to enter (or lock) in the same criti-
cal section to be executed. It is implemented by following methods of Object class:
• wait()
• notify()
• notifyAll()
All these methods belong to object class as final so that all classes have them. They must
be used within a synchronized block only.
1) wait() method
Causes current thread to release the lock and wait until either another thread invokes the
notify() method or the notifyAll() method for this object, or a specified amount of time has
elapsed. The current thread must own this object’s monitor, so it must be called from the syn-
chronized method only otherwise it will throw exception.
2) notify() method
Wakes up a single thread that is waiting on this object’s monitor. If any threads are waiting
on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the
discretion of the implementation. Syntax:
public final void notify()
3) notifyAll() method
Wakes up all threads that are waiting on this object’s monitor. Syntax:
public final void notifyAll()
// Java program to demonstrate inter-thread communication (wait(), join() and notify()) in
Java
import java.util.Scanner;
public class Thread_Example
{
public static void main(String[] args) throws InterruptedException
{
final Producer_Consumer pc = new Producer_Consumer ();
Thread t1 = new Thread(new Runnable()
{
public void run()
{
30
try
{
pc.producer();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable()
{
public void run()
{
try
{
pc.consumer();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
31
public static class Producer_Consumer
{
public void producer()throws InterruptedException
{
synchronized(this)
{
System.out.println(“producer thread running”);
wait();
System.out.println(“Resumed”);
}
}
public void consumer()throws InterruptedException
{
Thread.sleep(1000);
Scanner ip = new Scanner(System.in);
synchronized(this)
{
System.out.println(“Waiting for return key.”);
ip.nextLine();
System.out.println(“Return key pressed”);
notify();
Thread.sleep(1000);
}
}
}
}
The following statements explain how the above producer-Consumer program works.
• The use of synchronized block ensures that only one thread at a time runs. Also since
there is a sleep method just at the beginning of consumer loop, the produce thread
gets a kickstart.
32
• When the wait is called in producer method, it does two things.
1. it releases the lock it holds on PC object.
2. it makes the produce thread to go on a waiting state until all other threads have
terminated, that is it can again acquire a lock on PC object and some other
method wakes it up by invoking notify or notifyAll on the same object.
• Therefore we see that as soon as wait is called, the control transfers to consume thread
and it prints -“Waiting for return key”.
• After we press the return key, consume method invokes notify(). It also does 2 things-
Firstly, unlike wait(), it does not releases the lock on shared resource therefore for
getting the desired result, it is advised to use notify only at the end of your method.
Secondly, it notifies the waiting threads that now they can wake up but only after the
current method terminates.
• As you might have observed that even after notifying, the control does not immediately
passes over to the produce thread. The reason for it being that we have called Thread.
sleep() after notify(). As we already know that the consume thread is holding a lock
on PC object, another thread cannot access it until it has released the lock. Hence only
after the consume thread finishes its sleep time and thereafter terminates by itself, the
produce thread cannot take back the control.
• After a 2 second pause, the program terminates to its completion.
• The following program is one more example for interthread communication
class InterThread_Example
{
public static void main(String arg[])
{
final Client c = new Client();
new Thread()
{
public void run()
{
c.withdraw(15000);
}
}.start();
33
new Thread()
{
public void run()
{
c.deposit(10000);
}
}.start();
new Thread()
{
public void run()
{
c.deposit(10000);
}
}.start();
}
}
class Client
{
int amount = 10000;
34
{
System.out.println(“Insufficient Balance waiting for deposit.”);
try
{
wait();
} catch (Exception e)
{
System.out.println(“Interruption Occured”);
}
}
this.amount -= amount;
System.out.println(“Detected amount: “ + amount);
System.out.println(“Balance amount : “ + this.amount);
}
synchronized void deposit(int amount)
{
System.out.println(“Going to deposit “ + amount);
this.amount += amount;
System.out.println(“Available Balance “ + this.amount);
System.out.println(“Transaction completed.\n”);
notify();
}
}
4.5 DAEMON THREAD
Daemon thread is a low priority thread that runs in background to perform tasks such as
garbage collection. Daemon thread in java is a service provider thread that provides services
to the user thread. Its life depend on the mercy of user threads i.e. when all the user threads
dies, JVM terminates this thread automatically.
35
There are many java daemon threads running automatically e.g. gc, finalizer etc.
• It provides services to user threads for background supporting tasks. It has no role in
life than to serve user threads.
• Its life depends on user threads.
• It is a low priority thread.
The command jconsole typed in the command prompt provides information about the
loaded classes, memory usage, running threads etc.
The purpose of the daemon thread is that it provides services to user thread for back-
ground supporting task. If there is no user thread, why should JVM keep running this thread.
That is why JVM terminates the daemon thread if there is no user thread.
Properties:
• They cannot prevent the JVM from exiting when all the user threads finish their
execution.
• JVM terminates itself when all user threads finish their execution
• If JVM finds running daemon thread, it terminates the thread and after that shutdown
itself. JVM does not care whether Daemon thread is running or not.
• It is an utmost low priority thread.
Methods for Java Daemon thread by Thread class
The java.lang.Thread class provides two methods for java daemon thread.
Method Description
public void setDaemon(boolean status) used to mark the current thread as daemon
thread or user thread.
public boolean isDaemon() used to check that current is daemon.
// Java program to demonstrate the usage of setDaemon() and isDaemon() method.
public class DaemonThread extends Thread
{
public void run()
{
// Checking whether the thread is Daemon or not
if(Thread.currentThread().isDaemon())
{
System.out.println(“This is Daemon thread”);
36
}
else
{
System.out.println(“This is User thread”);
}
}
37
System.out.println(“Thread name: “ + Thread.currentThread().getName());
System.out.println(“Check if its DaemonThread: “
+ Thread.currentThread().isDaemon());
}
public static void main(String[] args)
{
DaemonThread t1 = new DaemonThread();
DaemonThread t2 = new DaemonThread();
t1.start();
// Exception as the thread is already started
t1.setDaemon(true);
t2.start();
}
}
Output:
Thread name: Thread-0
Check if its DaemonThread: false
Daemon vs User Threads
• Priority: When the only remaining threads in a process are daemon threads, the
interpreter exits. This makes sense because when only daemon threads remain, there
is no other thread for which a daemon thread can provide a service.
• Usage: Daemon thread is to provide services to user thread for background supporting
task.
The following program is an example for daemon thread.
public class DaemonThread_example extends Thread{
public void run(){
if(Thread.currentThread().isDaemon()){//checking for daemon thread
System.out.println(“daemon thread work”);
}
else{
38
System.out.println(“user thread work”);
}
}
public static void main(String[] args){
TestDaemonThread1 t1=new TestDaemonThread1();//creating thread
TestDaemonThread1 t2=new TestDaemonThread1();
TestDaemonThread1 t3=new TestDaemonThread1();
t1.setDaemon(true);//now t1 is daemon thread
t1.start();//starting threads
t2.start();
t3.start();
}
}
The following program is another example for daemon thread.
class DaemonThread1_example extends Thread{
public void run(){
System.out.println(“Name: “+Thread.currentThread().getName());
System.out.println(“Daemon: “+Thread.currentThread().isDaemon());
}
public static void main(String[] args){
TestDaemonThread2 t1=new TestDaemonThread2();
TestDaemonThread2 t2=new TestDaemonThread2();
t1.start();
t1.setDaemon(true);//will throw exception here
t2.start();
}
}
39
4.6 THREAD GROUP IN JAVA
Java provides a convenient way to group multiple threads in a single object. In such way,
we can suspend, resume or interrupt group of threads by a single method call. ThreadGroup
creates a group of threads. It offers a convenient way to manage groups of threads as a unit.
This is particularly valuable in situation in which you want to suspend and resume a number
of related threads.
• The thread group form a tree in which every thread group except the initial thread
group has a parent.
• A thread is allowed to access information about its own thread group but not to access
information about its thread group’s parent thread group or any other thread group.
Constructors of ThreadGroup class
There are only two constructors of ThreadGroup class.
Constructor Description
Thread Group (String name) creates a thread group with given name.
Thread Group (ThreadGroup parent, creates a thread group with given parent group
String name) and name.
The following program is an example for ThreadGroup
public class ThreadGroup_example implements Runnable{
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
ThreadGroup_example runnable = new ThreadGroup_example();
ThreadGroup tg1 = new ThreadGroup(“Parent ThreadGroup”);
Thread t1 = new Thread(tg1, runnable,”one”);
t1.start();
Thread t2 = new Thread(tg1, runnable,”two”);
t2.start();
Thread t3 = new Thread(tg1, runnable,”three”);
t3.start();
40
System.out.println(“Thread Group Name: “+tg1.getName());
tg1.list();
}
}
Sample Output:
one
two
three
Thread Group Name: Parent ThreadGroup
java.lang.ThreadGroup[name=Parent ThreadGroup,maxpri=10]
Thread [one,5,Parent ThreadGroup]
Thread [two,5,Parent ThreadGroup]
Thread [three,5,Parent ThreadGroup]
Methods of ThreadGroup class
There are many methods in ThreadGroup class. A list of important methods are given
below.
Method Description
void destroy() destroys this thread group and all its sub groups.
41
The following programs explain the threadgroup example.
// Java code illustrating activeCount() method
import java.lang.*;
class NewThread extends Thread
{
NewThread(String threadname, ThreadGroup tgob)
{
super(tgob, threadname);
start();
}
public void run()
{
42
// creating the thread group
ThreadGroup gfg = new ThreadGroup(“parent thread group”);
43
Module – 5
Enumerations , Autoboxing
Enumerations
• Enumeration fundamentals
• the values() and valueOf() Methods
• java enumerations are class types
• enumerations Inherits Enum, example
• type wrappers
Autoboxing
• Autoboxing and Methods
• Autoboxing/Unboxing occurs in Expressions
• Autoboxing/Unboxing Boolean and character values
Creating Enumerations
• When creating an enumeration list, we don't use the keyword class and when you
create a enumeration object, we don't use the keyword new
• To create an enumeration list we need to import java.util.Enumeration
• An enumeration is created using the enum keyword followed by the variable
Name we want associated with the list
Syntax:
example:
public enum Gender {
MALE, FEMALE, UNKNOWN
}
To declare an enumeration object, use the variable name associated with the list followed by the
name of the object.
To assign values to the object, must use the enumeration name, a dot and one of the values in the
list.
We can also assign the default value to list of item in enumeration class. In order to assign
default value to list in enumeration class, should contain the enumeration
constructor,fields,methods.
Simple Program:
enum Gender {
MALE, FEMALE, UNKNOWN
}
class Enu
{
public static void main( String args[] )
OUTPUT:
Gender IS=MALE
1. Simple if Statement:
The Java if statement tests the condition. It executes the if block if condition is true.
Syntax: if(condition)code to be executed
Program:
enum Gender {
MALE, FEMALE, UNKNOWN;
class cont
{
}
}
program 2: To find Smallest of given number.
enum Value {
a(10), b(20);
int a1;
int getValue(){ return a1;}
Value(int value)
{
this.a1=value;
}
}
class Enu
{
public static void main( String args[] )
{
int s=Value.a.getValue();
if(s<Value.b.getValue())
System.out.println("a value is small");
}
}
2) if else: The Java if-else statement also tests the condition. It executes the if block if condition is true
otherwise else block is executed.
Syntax: if(condition) //code if condition is true
else
class cont
{
public static void main( String args[] )
{
Gender s=Gender.FEMALE;
if(s==Gender.MALE)
System.out.println("both are equal");
else
System.out.println("Both are not equal");
}
}
output: Both are not equal
enum Value {
a(10), b(20);
int a1;
int getValue(){ return a1;}
Value(int value)
{
this.a1=value;
}
}
class Enu
{
public static void main( String args[] )
{
int s=Value.a.getValue();
if(s<Value.b.getValue())
System.out.println("a value is small");
else
System.out.println("b value is small");
}
}
output: a value is small
program 1:
enum Gender {
MALE, FEMALE, UNKNOWN;
class cont
{
public static void main( String args[] )
{
Gender s=Gender.FEMALE;
if(s==Gender.MALE)
System.out.println("both are equal");
else if (s==Gender.UNKNOWN)
System.out.println("Both are equal");
else
System.out.println("Both are not equal");
}
}
program 2:
enum Value {
a(10), b(20), c(30);
int a1;
int getValue(){ return a1;}
class Enu
{
public static void main( String args[] )
{
int s=Value.a.getValue();
if(s<Value.b.getValue())
System.out.println("a value is small compare to b");
else if(s<Value.c.getValue())
System.out.println("a value is small comapare to c");
else
System.out.println("a value is grater");
}
}
output: a value is small compare to b
Switch Statement:
When there are several options and we have to choose only one option from the available
ones, we can use switch statement.
Syntax: switch (expression)
{ case value1: //statement sequence
break;
case value2: //statement sequence
break;
case valueN: //statement sequence
break;
default: //default statement sequence
}
program 1: To check the gender of person
enum Gender {
MALE, FEMALE, UNKNOWN;
class cont
{
public static void main( String args[] )
{
Gender s=Gender.FEMALE;
switch(s)
{
case MALE:System.out.print("Gender is mail");
break;
case FEMALE:System.out.print("Gender is femail");
break;
case UNKNOWN:System.out.print("Gender is unknown");
break;
default:System.out.print("NON of these");
}
}
}
output: Gender is femail
Java’s Iteration Statements: Java’s iteration statements are for, while and do-while. These
statements are used to repeat same set of instructions specified number of times called loops
Types of looping statements are:
1) while
2) do while
3)for
1) while Loop: while loop repeats a group of statements as long as condition is true. Once
the condition is false, the loop is terminated. In while loop, the condition is tested first; if
it is true, then only the statements are executed. while loop is called as entry control loop.
Syntax: while (condition)
{
statements;
}
Program: To find Sum of given number:
int a1;
int getValue(){ return a1;}
Value(int value)
{
this.a1=value;
}
}
class Enu
{
public static void main( String args[] )
{
int n=Value.NUM.getValue();
int sum=0,i=0;
while( i<n)
{
sum+=i;
i++;
}
System.out.println("sum of given number is="+sum);
}
}
output: sum of given number is=45
2) do while Loop: do…while loop repeats a group of statements as long as condition is
true. In do...while loop, the statements are executed first and then the condition is tested.
do…while loop is also called as exit control loop.
Syntax: do
{
statements;
} while (condition);
Program: To find sum of given number:
enum Value {
NUM(10);
int a1;
int getValue(){ return a1;}
Value(int value)
class Enu
{
public static void main( String args[] )
{
int n=Value.NUM.getValue();
int sum=0,i=0;
do
{
sum+=i;
i++;
}while( i<n);
System.out.println("sum of given number is="+sum);
}
}
output: sum of given number is=45
3.for Loop: The for loop is also same as do…while or while loop, but it is more compact
syntactically. The for loop executes a group of statements as long as a condition is true.
Syntax: for (expression1; expression2; expression3)
{ statements;
}
Here, expression1 is used to initialize the variables, expression2 is used for condition
checking and expression3 is used for increment or decrement variable value.
program : To find the sum of given number.
enum Value {
NUM(10);
int a1;
int getValue(){ return a1;}
Value(int value)
{
this.a1=value;
}
}
class Enu
• Enumerations in Java can have methods, members and constructors just as any other class
can have.
• Each enumeration constant is an object of its enumeration type.
• Thus, when you define a constructor for an enum, the constructor is called when each
enumeration constant is created.
• Also, each enumeration constant has its own copy of any instance variables defined by
the enumeration.
• the enum constants have initial value that starts from 0, 1, 2, 3 and so on. But we can
initialize the specific value(default value) to the enum constants by defining fields and
constructors.
Syntax:
enum variableName
{
ITEM1(1), ITEM2(20), ITEM3(30);
data-typevariableName;
data-type methodName()
{ statement;}
enumName (parameter-list) {
statements;
}
Progarm:
enum Value {
A(10), B(20), C(30);
int a;
int getValue(){ return a;}
class Enu
{
public static void main( String args[] )
{
There are some methods that you can use that are part of the enumeration class, these methods
include :
1. values()
2. valueOf()
1.Values():
enum month {
January(31),
February(28),
March(31),
April(30),
May(31),
June(30),
July(31),
August(31),
September(30),
October(31),
November(30),
December(31);
month(int days) {
this.days = days;
}
}}
output:
January:31
February:28
March:31
April:30
May:31
June:30
July:31
August:31
September:30
October:31
November:30
December:31
2. ValueOf():
• method returns the enumeration constant whose value corresponds to the string
passed in str.
• method takes a single parameter of the constant name to retrieve and returns the constant
from the enumeration, if it exists.
Syntax: enumerationVariable = enumerationName.valueOf("EnumerationValueInList");
Example
WeekDays wd = WeekDays.valueOf("MONDAY");
System.out.println(wd);
program:
enum Days {
monday,tuesday;
class cont
{
public static void main( String args[] )
{
Days d=Days.valueOf("monday");
System.out.println("day selected is:"+d);
}
}
output: day selected is:Monday
1. ordinal():
• Returns the value of the constant's position in the list (the first constant has a position
of zero).
• The ordinal value provides the order of the constant in the enumeration, starting with
0
Example
WeekDays wd = WeekDays.MONDAY;
System.out.println(wd.ordinal());
enum Days {
mon,tue,wed;
}
class cont
{
2. compareTo():
• compares the ordinal value of the two enumeration objects.
• If the object invoking the method has a value less than the object being passed, a negative
number is returned.
• It the two objects have the same oridnal number, a zero is returned.
• If the invoking object has a greater value than the one being passed, a positive number is
returned.
Syntax: int num = enumObject1.compareTo(enumObject2);
enum Days {
mon,tue,wed;
}
class cont
{
}
}
output:
mon comes befor tue
Tue comes befor wed
wed comes after tue
method returns the name of this enum constant, as contained in the declaration.
public String toString()
This method returns the name of this enum constant.
Example:
enum Days {
mon,tue,wed;
}
class cont
{
public static void main( String args[] )
{
Days d1,d2,d3;
d1=Days.mon;
d2=Days.tue;
d3=Days.wed;
System.out.println(d1.toString());
System.out.println(d2. toString());
System.out.println(d3. toString());
}
Ms. Jeevitha R OOP with Java Page 20
Ms. Jeevitha R OOP with Java Page 21
}
Output: mon tue wed
4.Type wrappers:
▪ Java uses primitive types (also called simple types), such as int or double, to
hold the basic data types supported by the language.
• Instead of primitive types if objects are used everywhere for even simple
calculations then performance overhead is the problem.
• So to avoid this java had used primitive types.
• So primitive types do not inherit Object class
• But there are times when you will need an object representation for
primitives like int and char.
• Example, you can’t pass a primitive type by reference to a method.
• Many of the standard data structures implemented by Java operate on objects,
which mean that you can’t use these data structures to store primitive types.
• To handle these (and other) situations, Java provides type wrappers, which
are classes that encapsulate a primitive type within an object.
Character:
• Character is a wrapper around a char.
• The constructor for Character is Character(char ch) here ch is a character
variable whose values will be wrapped to character object by the wrapper class
• To obtain the char value contained in a Character object, call charValue( ), shown
here:
char charValue( )
It returns the encapsulated character.
Boolean
• In the first version, boolValue must be either true or false. In the second version, if
boolString contains the string "true" (in uppercase or lowercase), then the new Boolean
object will be true. Otherwise, it will be false.
• To obtain a boolean value from a Boolean object, use booleanValue( ), shown here:
• The most commonly used type wrappers are those that represent numeric values. These are
Byte, Short, Integer, Long, Float, and Double. All of the numeric type wrappers inherit
the abstract class Number.
• Number declares methods that return the value of an object in each of the different number
formats. These methods are shown here:
1. byte byteValue( )
2. double doubleValue( )
3. float floatValue( )
4. int intValue( )
5. long longValue( )
6. short shortValue( )
class Wrap {
public static void main(String args[]) {
output:
Autoboxing
Program:
class auto {
public static void main(String args[]) {
Integer iOb, iOb2; int i;
iOb = 100;
System.out.println("Original value of iOb: " + iOb); //The following
automatically unboxes iOb, performs the increment,
and then reboxes the result back into iOb.
++iOb;
System.out.println("After ++iOb: " + iOb);
iOb2 = iOb + (iOb / 3);
System.out.println("iOb2 after expression: " + iOb2);
i = iOb + (iOb / 3);
System.out.println("i after expression: " + i);
}
}
output:
Original value of iOb: 100
After ++iOb: 101
iOb2 after expression: 134
i after expression: 134
class auto {
public static void main(String args[]) {
//Autobox/unbox a boolean.
Boolean b = true;
if(b)
System.out.println("b is true");
}
}
output:
b is true
ch2 is x