Documente Academic
Documente Profesional
Documente Cultură
JAVA/ J2EE
Notes prepared by
Mr. Ashok Kumar K
9742024066 | celestialcluster@gmail.com
www.vtuprojects.com | Final year IEEE project development and training from scratch by Mr. Ashok Kumar K.
Registration started. Contact 9742013378 or 9742024066 and lock your project at the earliest.
Unit 3:
Multithreaded Programming,
Event Handling
MULTITHREADED PROGRAMMING
Concurrency is the ability to run multiple parts of the program in parallel. If a program can be divided into multiple independent parts,
each performing a specific task, then executing these parts in parallel in an asynchronous way increases the throughput of the program.
This type of programming is generally referred to as Concurrent Programming.
Process Thread
Definition: Definition:
Process is an instance of an entire program Thread is an execution path or the control
in execution. flow of execution of a program.
A process has a separate execution Threads exist within a process; every process
environment. It has a complete, private set of has at least one thread. Threads share the
basic run-time resources; each process has process's resources, including memory and
its own memory space open files. Threads are called light-weight
process
Remember:
Threads have their own call stack and can access shared data. These cause two problems
Visibility problem occurs if thread A reads shared data and thread B later changes this data and the thread A is unaware of this
change.
Access problem can occur if several threads tries to access and share the same shared data at the same time.
A separate process will be created for each Java program within which one default thread (called the Main thread) starts executing the
main function. This default thread or the main thread will be created by JVM. You can also create child threads using this.
It is the thread using which other threads (child threads) can be created
Ideally it must be the last thread to finish execution because it performs various shutdown operations.
Below example does some exercise with the main thread. It first gets the access (reference) to main thread using currentThread()
method in Thread class. It prints the name of the thread whose reference we have just got. It changes the name and priority of the
thread using setName() and setPriority() methods respectively. It prints the numbers 0 through 4 with a delay of 1sec after each
number. The thread is made to sleep for 1 sec after printing one number. A thread can be sent to sleep using Thread.sleep(long)
method where the parameter is the amount of time in milliseconds.
Output
When you simply print a thread reference t, you know that it will invoke t.getString() method which printed something like this:
Thread[main, 5, main]. Here is what actually they are:
Step 1:
Simply define your own class and implement it by java.lang.Runnable interface. Define run() method and include the
business logic of the thread within the run() method, because run() is the entry point for a thread and when it returns
from this function, the thread dies. To put it differently, a thread will be active till it lies in the context of run() method.
Instance of this class is called Runnable object since it implements Runnable interface.
Step 2:
Creating a child thread is nothing but creating an instance of Thread class and passing the runnable object as a
parameter for its constructor. Remember, at this point of time you have only created a child thread, but you haven't
started its execution yet. To do so, you should invoke start() method of the thread object you just created. It causes the
child thread to start its execution. The JVM calls run() method of the child thread. The result is that two threads are
running concurrently: the current thread (which returns from the call to the start method) and the other thread (which
executes its run() method).
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed
execution.
try {
for (int i = 0; i < 5; i++) {
Mr. Ashok Kumar K | 9742024066 | celestialcluster@gmail.com
www.vtuprojects.com | Final year IEEE project development and training from scratch by Mr. Ashok Kumar K.
Registration started. Contact 9742013378 or 9742024066 and lock your project at the earliest.
Thread.sleep(1000);
System.out.println("Main .. " + i);
}
System.out.println("Main thread exiting .. ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Output:
The order of execution of two threads is not the same always. The output you are seeing above can't be predicted.
Since the main thread and the child thread both are executing in parallel you can't expect the same ordering all the time.
It just gets mixed up.
Observation:
As a component developer you should focus on both the business logic and the required resources to create a thread.
An application developer will simply makes use of this. What I meant to tell is you should allow full freedom to the user of
this thread. You should encapsulate the process of creating a thread within the custom Thread class itself, as shown
below;
MyThread() {
t = new Thread(this);
t.start();
}
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("Main .. " + i);
}
System.out.println("Main thread exiting .. ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Step 1:
Simply extend your own class with java.lang.Thread. Define run() method and include the business logic of the
thread within the run() method, because run() is the entry point for a thread and when it returns from this function, the
thread dies.
Step 2:
Creating a thread is just creating an instance of the class defined in step 1. To begin the execution of the child thread,
you should invoke the run() method of the object created.
try {
Mr. Ashok Kumar K | 9742024066 | celestialcluster@gmail.com
www.vtuprojects.com | Final year IEEE project development and training from scratch by Mr. Ashok Kumar K.
Registration started. Contact 9742013378 or 9742024066 and lock your project at the earliest.
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("Main .. " + i);
}
System.out.println("Main thread exiting .. ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Observation:
As discusses previously, the logic of creating a thread should be encapsulated within the Thread class by the
component developer. Here is the optimized version of the above program.
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("Main .. " + i);
}
System.out.println("Main thread exiting .. ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Creating a thread by implementing Runnable interface is preferred over extending the Thread class for two reasons.
Inheritance should be done only if you are modifying or enhancing the base class behavior. Since our class doesn't modify or
enhance the Thread class behavior, extending the Thread class is not recommended.
If you extend the Thread class, you now don't have freedom of extending other classes (since multiple inheritances are not
allowed). So we prefer implementing the Runnable interface and extending any other class.
You can create as many threads as you want. Below example creates four threads and starts them so that the four child threads along
with the main thread prints the numbers 0 to 4 concurrently. One more thing you need to observe from below program is the method of
assigning a name to the child thread. Yes, you can set the name of a child thread by passing the name as a String argument to the
Thread class constructor.
MyThread(String name) {
t = new Thread(this, name); // 'name' is the child thread's name
t.start();
}
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("Main .. " + i);
}
System.out.println("Main thread exiting .. ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Mr. Ashok Kumar K | 9742024066 | celestialcluster@gmail.com
www.vtuprojects.com | Final year IEEE project development and training from scratch by Mr. Ashok Kumar K.
Registration started. Contact 9742013378 or 9742024066 and lock your project at the earliest.
Output
You can clearly see the order in which these threads execute can't be predicted. It depends on many things including the thread
priority.
There are three possible methods to make the main thread wait till all its child threads get terminated.
Method 1:
Make the main thread to sleep for some specified amount of time just before its termination, so that all its child threads can
MyThread(String name) {
t = new Thread(this, name);
t.start();
}
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("Main .. " + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
Output:
Drawback:
How will you choose the amount of time that the main thread should sleep to ensure the termination of all its child threads?
You would end up choosing some large amount of time therefore making the main thread sleep for some extra time
even though all its child threads are already terminated.
You would end up choosing lesser time giving no time for some of its child threads to terminate.
Method 2:
Main thread can invoke isAlive() method on each of its child threads to see if it is still running or already terminated. This
way, the main thread will be in a continuous loop until all the child threads gets terminated. isAlive() is a method defined in
Thread class and have the signature as follows:
It returns true if the thread upon which it is called is still running. It returns false otherwise.
Example
MyThread(String name) {
t = new Thread(this, name);
t.start();
}
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("Main .. " + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
// Main Thread will come out of this loop only after all the threads
terminates
while (true) {
if (m1.t.isAlive() || m2.t.isAlive() || m3.t.isAlive() ||
m4.t.isAlive()) {
// loop again
}
else
break; // come out of the loop
}
System.out.println("Main thread exiting .. ");
}
Output
Drawback:
This method has unspecified amount of continuous looping to check the status of the child threads thus wasting the runtime
resources.
Method 3:
join() is the method we mostly use to wait for a thread to finish its execution. join() method is also defined in Thread class
with the signature as follows:
This method waits until the thread on which it is called terminates. Additional forms of join( ) allow you to specify a
maximum amount of time that you want to wait for the specified thread to terminate.
Example
MyThread(String name) {
t = new Thread(this, name);
t.start();
}
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("Main .. " + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
m1.t.join();
m2.t.join();
m3.t.join();
m4.t.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main thread exiting .. ");
}
Output:
Each thread in Java will have an associated priority which is an integer value ranging from 1 (minimum) to 10 (maximum). Thread
scheduler will use the thread priorities to determine the execution schedule of threads. Higher priority threads get the CPU much faster
than the lower priority threads. If two threads have the same priority, the thread scheduler treats them equally and serves them based
on First Come First Serve (FCFS) basis.
Thread class defines two methods, one for setting the thread priority and the other for returning the current priority of a thread. Their
signatures are as follows:
void setPriority(int); sets the priority of a calling thread to the one passed as an argument.
int getPriority(); returns the current priority of the calling thread
Priority range
Example:
try {
Thread.sleep(10000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Low priority thread's execution count ..
"+m1.count);
System.out.println("High priority thread's execution count ..
"+m2.count);
}
}
Output:
As you can see, for the duration of 10 seconds the high priority thread has been given more CPU cycles compared to the low priority
thread.
Definition
Whenever two or more threads accesses the shared resources we need some mechanism to make sure that only one thread is given
access to the shared resource at any point of time. The process by which this is achieved is called synchronization.
Visibility problem: It occurs if thread A reads shared data and thread B later changes this data and the thread A is unaware of
this change.
Access problem: It occurs if several threads tries to access and share the same shared data at the same time.
The block of code or in general any resources, which is shared among more than two threads and which needs to be synchronized, is
called a monitor (also known as semaphore). Only one thread can access the monitor at any point of time. When a thread enters the
monitor, we say that the thread has acquired the lock, and it prevents any other threads entering into the same monitor until it releases
the lock by exiting the monitor.
Problem demonstration
Below program has a class named Utility which defines a method called printMessage(String). It takes a string argument and prints it
within the flower braces { and }. When two threads accesses this method at the same time each one passing a different string
argument, the order in which these messages are printed are not jumbled (mixed up).
class Utility {
// this is the shared resource
public void printMessage(String msg) {
System.out.print("{");
System.out.print(msg);
System.out.println("}");
}
}
}
}
Mr. Ashok Kumar K | 9742024066 | celestialcluster@gmail.com
www.vtuprojects.com | Final year IEEE project development and training from scratch by Mr. Ashok Kumar K.
Registration started. Contact 9742013378 or 9742024066 and lock your project at the earliest.
Output
Synchronized methods
This solution is simple. Just prefix the keyword 'synchronized' to the shared resource which needs to be
synchronized. The resource can be a method, variable or any other program elements. Here the shared resource is
the printMessage() method.
class Utility {
// shared resource is synchronized
synchronized public void printMessage(String msg) {
System.out.print("{");
System.out.print(msg);
System.out.println("}");
}
}
}
}
Output
Synchronized blocks
The solution described above is simple and accepted as long as you have the access to Utility class so that you can
modify it and add synchronized keyword. But, what if you are not the owner of Utility class? Meaning, you are not
authorized to modify the class and you cannot add the synchronized keyword to its method.
In these situations, you can go with synchronized blocks. Simply put calls to the methods defined by this class inside
a synchronized block. This is the general form of the synchronized statement:
synchronized(object) {
// statements to be synchronized
}
Here, object is a reference to the object being synchronized. A synchronized block ensures that a call to a method
that is a member of object occurs only after the current thread has successfully entered object’s monitor.
class Utility {
public void printMessage(String msg) {
System.out.print("{");
System.out.print(msg);
System.out.println("}");
}
}
Output
wait():
This method 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():
This method wakes up the first thread that called wait() on the same object.
notifyAll():
This method wakes up all the threads that called wait() on the same object. The highest priority thread will run
first.
class Q {
int n;
boolean valueSet = false;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
Output:
Below figure shows the various states of a thread and its life cycle starting from New state to Terminated state.
Delegation Event Model constitutes of three entities: event, source, and listener.
Event
Event is an object that describes the state change. These objects are encapsulated in a class hierarchy rooted at
java.util.EventObject. An event is propagated from a "Source" object to a "Listener" object by invoking a method on the listener
and passing in the instance of the event subclass which defines the event type generated.
Source
An Event Source is an object which originates or "fires" events. (Example, an Applet). A source must register listeners in order for the
listeners to receive notifications about a specific type of event.
Registering a listener:
Each type of event has its own registration method. Here is the general form:
Here, Type is the name of the event, and el is a reference to the event listener. For example, the method
that registers a keyboard event listener is called addKeyListener(). The method that registers a mouse
motion listener is called addMouseMotionListener().
Unregistering a listener:
A source must also provide a method that allows a listener to unregister an interest in a specific type of
event. The general form of such a method is this:
Here, Type is the name of the event, and el is a reference to the event listener. For example,
to remove a keyboard listener, you would call removeKeyListener( ).
Listener
A listener is an object which will be notified when an event occurs. A Listener is an object that implements a specific EventListener
interface extended from the generic java.util.EventListener.
First, it must have been registered with one or more sources to receive notifications about specific types of events.
Second, it must implement methods to receive and process these notifications
3.11 Event
Almost for every possible type of event that can occur (Ex, click a button, scroll the mouse, etc), Java defines a separate class for it.
java.util.EventObject is the root of all the event classes. The class java.awt.AWTEvent, is a subclass of EventObject. It is the
superclass (either directly or indirectly) of all AWT-based events used by the delegation event model.
The package java.awt.event defines various event classes to describe the events generated by various user interface elements.
Here are the few:
KeyEvent
A KeyEvent is generated when keyboard input occurs. There are three types of key events, which are identified by these integer
constants:
KEY_PRESSED
KEY_RELEASED, and
KEY_TYPED.
The first two events are generated when any key is pressed or released. The last event occurs only when a character is generated.
Remember, not all key presses result in characters. For example, pressing SHIFT does not generate a character.
There are many other integer constants that are defined by KeyEvent.
Mr. Ashok Kumar K | 9742024066 | celestialcluster@gmail.com
www.vtuprojects.com | Final year IEEE project development and training from scratch by Mr. Ashok Kumar K.
Registration started. Contact 9742013378 or 9742024066 and lock your project at the earliest.
For example,
VK_0 through VK_9 and VK_A through VK_Z define the ASCII equivalents of the numbers and letters.
Here are some others:
VK_ALT VK_DOWN VK_LEFT VK_RIGHT
VK_CANCEL VK_ENTER VK_PAGE_DOWN VK_SHIFT
VK_CONTROL VK_ESCAPE VK_PAGE_UP VK_UP
The KeyEvent class defines several methods, but the most commonly used ones are getKeyChar( ), which returns the character that
was entered, and getKeyCode( ), which returns the key code. Their general forms are shown here:
char getKeyChar( )
int getKeyCode( )
MouseEvent
There are eight types of mouse events. The MouseEvent class defines the following integer constants that can be used to identify them:
Two commonly used methods in this class are getX( ) and getY( ). These returns the X and Y coordinate of the mouse within the
component when the event occurred. Their forms are shown here:
int getX()
int getY()
Table below lists some of the user interface components that can generate the events described in the previous section.
Listeners are created by implementing one or more of the interfaces defined by the java.awt.event package. When an event occurs,
the event source invokes the appropriate method defined by the listener and provides an event object as its argument. Table below lists
commonly used listener interfaces and provides a brief description of the methods that they define.
KeyListener interface
MouseListener interface
MouseMotionListener interface
To handle mouse events, you must implement the MouseListener and the MouseMotionListener interfaces. The following applet
demonstrates the process.
o It displays the current coordinates of the mouse in the applet’s status window.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
Output:
To handle key board events, you will be implementing KeyListener interface. Before going to the program, Let's see how key events are
generated.
o When a key is pressed, a KEY_PRESSED event is generated. This results in a call to the keyPressed() event
handler.
o When the key is released, a KEY_RELEASED event is generated and the keyReleased( ) handler is executed.
o If a character is generated by the keystroke, then a KEY_TYPED event is sent and the keyTyped( ) handler is
invoked.
Thus, each time the user presses a key, at least two and often three events are generated.
Here is the program to demonstrate the handling of key events.
import java.awt.*;
import java.awt.event.*;
Output
Definition
An adapter class provides an empty implementation of all methods in an event listener interface. Adapter classes are useful when you
want to receive and process ONLY some of the events that are handled by a particular event listener interface. You can define a new
Table below shows Commonly Used Listener Interfaces Implemented by Adapter Classes.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
Till now we have seen how to handle events by using “this” reference.
Inner classes
Below example shows how to handle the events by using an inner class.
import java.applet.*;
import java.awt.event.*;
Advantage of handling the event by using inner class is that, the inner class can directly call the showStatus() method, and there is no
need to store a reference to the applet.
An anonymous inner class is one that is not assigned a name. This example illustrates how to use anonymous inner class to handle
events.
import java.applet.*;
import java.awt.event.*;
The syntax new MouseAdapter( ) { ... } indicates to the compiler that the code between the braces defines an anonymous inner class.
Furthermore, that class extends MouseAdapter. This new class is not named, but it is automatically instantiated when this expression is
executed.