You are on page 1of 110

Object Oriented Concepts

(18CS45)

Module-IV

Dr. Sanchari Saha


AP, Dept of CSE,
CMRIT, Bengaluru
Course Objective:
This course (18CS45) will enable students to:
Learn fundamental features of object-oriented language and JAVA
Set up Java JDK environment to create, debug and run simple Java programs.
Create multi-threaded programs and event handling mechanisms.
Introduce event driven Graphical User Interface (GUI) programming using applets and
swings.

Course Outcome:
The student will be able to :
Explain the object-oriented concepts and JAVA.
Develop computer programs to solve real world problems in Java.
Develop simple GUI interfaces for a computer program to interact with users, and to
understand the event-based GUI handling principles using swings
CO-PO and CO-PSO Mapping

P P P P P P P
P P P P P P P P
Modules PO O O O S S S S
Course Outcomes Blooms Level O O O O O O O O
covered 5 1 1 1 O O O O
1 2 3 4 6 7 8 9
0 1 2 1 2 3 4

Explain Object-Oriented
CO1 Concepts in C++ and L2 1,2 2 3 3 2 - 2 - - 2 2 - 2 2 - 2 -
JAVA.
Develop computer
programs for solution of
CO2 L2 2,3 2 3 3 2 - 2 - - 2 2 - 2 2 - 2 -
real world problems in
Java.
Develop simple GUI
CO3 interfaces for L3 4,5 2 3 3 2 2 2 - - 2 2 - 2 2 - 2 -
interaction with users
Develop Graphical User
CO4 Interface (GUI) with use L3 5 2 3 3 3 2 2 - - 2 2 - 2 2 - 2 -
of Applets and Swings.
Text Book & Reference Book

Textbooks:
1. Sourav Sahay, Object Oriented Programming with C++ , 2nd Ed, Oxford University
Press,2006
2. Herbert Schildt, Java The Complete Reference, 7th Edition, Tata McGraw Hill, 2007.
Reference Books:
1. Mahesh Bhave and Sunil Patekar, "Programming with Java", First Edition, Pearson
Education,2008, ISBN:9788131720806
2. Herbert Schildt, The Complete Reference C++, 4th Edition, Tata McGraw Hill, 2003.
3. Stanley B.Lippmann, Josee Lajore, C++ Primer, 4th Edition, Pearson Education, 2005.
4. Rajkumar Buyya,S Thamarasi selvi, xingchen chu, Object oriented Programming with java,
Tata McGraw Hill education private limited.
5. Richard A Johnson, Introduction to Java Programming and OOAD, CENGAGE Learning.
6. E Balagurusamy, Programming with Java A primer, Tata McGraw Hill companies
Content

➢Chapter 1: Packages and Interfaces


▪ Packages
▪ Access Protection
▪ Importing Packages
▪ Interfaces
Content
➢Chapter 2: Multi-Threaded Programming
• What are threads?
• How to make the classes threadable
• Extending threads
• Implementing runnable
• Synchronization
• Changing state of the thread
• Bounded buffer problems
• producer consumer problems
Chapter 1: Packages
A package as the name suggests is a pack(group) of classes, interfaces
and other packages. In java we use packages to organize our classes and
interfaces. We have two types of packages in Java:
o built-in package and
o user-defined package.

There are many built-in packages such as java, lang, awt, javax, swing,
net, io, util, sql etc.
Packages
Built-in Packages
These packages consist of a large number of classes which are a part of Java API.
Some of the commonly used built-in packages are:
1) java.lang: Contains language support classes(e.g classed which defines primitive
data types, math operations). This package is automatically imported.
2) java.io: Contains classed for supporting input / output operations.
3) java.util: Contains utility classes which implement data structures like Linked
List, Dictionary and support ; for Date / Time operations.
4) java.applet: Contains classes for creating Applets.
5) java.awt: Contain classes for implementing the components for graphical user
interfaces (like button , ;menus etc).
6) java.net: Contain classes for supporting networking operations.
User-defined packages
These are the packages that are defined by the user. First we create a
directory myPackage (name should be same as the name of the package). Then
create the MyClass inside the directory with the first statement being the package
names.
Advantages of using a package in Java
• Reusability: While developing a project in java, we often feel
that there are few things that we are writing again and again in our
code. Using packages, you can create such things in form of classes
inside a package and whenever you need to perform that same task,
just import that package and use the class.
• Better Organization: Again, in large java projects where we
have several hundreds of classes, it is always required to group the
similar types of classes in a meaningful package name so that you can
organize your project better and when you need something you can
quickly locate it and use it, which improves the efficiency.
• Name Conflicts: We can define two classes with the same
name in different packages so to avoid name collision, we can use
packages
Steps for Creating & accessing package in Java
Steps:
• Create a package with a .class file
• set the classpath from the directory from which you would like to access. It
may be in a different drive and directory. Let us call it as a target directory.
• Write a program and use the file from the package.

Let us create a package called forest and place a class called Tiger in it.
Access the package from a different drive and directory.
1st Step: Create a package (forest) and place Tiger.class in it.
• Let us assume C:\snr is the current directory where we would like to create
the package.
• C:\snr > notepad Tiger.java
Order of Package Statement
The above program coding wise is very simple but is important to know
the steps of package creation:

package forest;
import java.util.*;
public class Tiger

package is a keyword of Java followed by the package name. Just writing


the package statement followed by the name creates a new package;
While create User Defined Packages Java, the order of statements is very
important. The order must be like this, else, compilation error.
1.Package statement
2.Import statement
3.Class declaration

If exists, the package statement must be first one in the program. If exists, the
import statement must be the second one. Our class declaration is the third. Any
order changes, it is a compilation error.
When the code is ready, the next job is compilation. We must compile with
package notation. Package notation uses –d compiler option as follows.
C:\snr > javac -d . Tiger.java
• The –d compiler option creates a new folder called forest and places the
Tiger.class in it. The dot (.) is an operating system's environment variable that
indicates the current directory. It is an instruction to the OS to create a
directory called forest and place the Tiger.class in it.
Using User Defined Packages Java
After creating the package let us use it.
2nd step: Set the classpath from the target directory.
Let us assume D:\sumathi is the target directory. Let us access Tiger.class in forest
package from here.
From the target directory set the classpath following way.
D:\sumathi> set classpath=C:\snr;%classpath%;
classpath is another environment variable which gives the address of the forest
directory to the OS. %classpath% informs the OS to append the already existing
classpath to the current classpath that is right now set.

3rd Step: Now finally, write a program from the target directory
D:/sumathi and access the package.

D:\sumathi> notepad Animal.java


The above statement creates a file called Animal.java and write the code in it,
say, as follows.
The compilation and execution is as usual as follows.
D:\sumathi> javac Animal.java
D:\sumathi> java Animal
Importing Packages

• All the standard classes in Java are stored in named packages.

• There is no standard class present in Java which is unnamed. But it is always


complicated to write the class name using a long sequence of packages
containing dot (.) operator. Hence the import statement is needed.

• The import statement can be written at the beginning of the Java program,
using the keyword import.
Various ways to access the package from outside
the package in Java using import
There are three ways to access the package from outside the package.

❑ import package.*;

❑ import package.classname;

❑ fully qualified name.


Various ways to access the package from outside
the package in Java using import
1) Using packagename.*

If you use package.* then all the classes and interfaces of this package will be
accessible but not sub packages.

The import keyword is used to make the classes and interface of another package
accessible to the current package.
Example of package that import the packagename.*

//save by A.java
package pack;
public class A
{
public void msg()
{System.out.println("Hello");}
Output: Hello
}
//save by B.java
package mypack;
import pack.*;
class B
{
public static void main(String args[])
{
A obj = new A();
obj.msg();
}}
2) Using packagename.classname
If you import package.classname then only declared class of
this package will be accessible.

Example of package by import package.classname


//save by A.java
package pack;
public class A
{
public void msg()
{System.out.println("Hello");
}
}

//save by B.java
package mypack;
import pack.A;
class B
{
public static void main(String args[])
{
A obj = new A();
obj.msg();
}
}
Output:Hello
3) Using fully qualified name

If you use fully qualified name, then only declared class of this
package will be accessible. Now there is no need to import. But
you need to use fully qualified name every time when you are
accessing the class or interface.

It is generally used when two packages have same class name e.g.
java.util and java.sql packages contain Date class.
Example of package by import fully qualified name
//save by A.java
package pack;
public class A
{
public void msg()
{
System.out.println("Hello");
}
}
//save by B.java
package mypack;
class B
{
public static void main(String args[])

{
pack.A obj = new pack.A(); //using fully qualified name
obj.msg();
}
}
Output:Hello
Access Protection
The access modifiers in java specify accessibility (scope) of a data member,
method, constructor or class.
There are 4 types of java access modifiers:
• private
• default
• protected
• public
private access modifier
The private access modifier is accessible only within class.
default access modifier
If you don't use any modifier, it is treated as default by default. The default
modifier is accessible only within package.
Access Protection
protected access modifier
The protected access modifier is accessible within package and outside the
package but through inheritance only.
The protected access modifier can be applied on the data member, method and
constructor. It can't be applied on the class.

public access modifier


The public access modifier is accessible everywhere. It has the widest scope
among all other modifiers.
Access within within outside package outside
Modifier class package by subclass only package
Private Y N N N
Default Y Y N N
Protected Y Y Y N
Public Y Y Y Y
Access Protection
If public or private specifier is not used then by default the classes,
methods, data fields are accessible by any class in the same package. This
is called package-private or package access.
A package is essentially grouping of classes.
Obj.a;//allowed
For Example: Obj.b//error
Obj.c;//error
Package another_Test; Obj.fun1();//allowed
Public class class3 Obj.fun2();//error
{ Obj.fun3();//error
Void My_method() }
{ }
Class1 Obj=new class1();
Access Protection
public void fun1()
Program -2 {

}
Package Test;
Public class class1 void fun2()
{ {
Public int a;
Int b; }
Private int c;
private void fun3()
{

}
public class class2
{
Void My_method()
{
class1 Obj=new class1()

Obj.a;//allowed
Obj.b//allowed
Obj.c;//error
Obj.fun1();//allowed
Obj.fun2();//allowed
Obj.fun3();//error
}
}
Interfaces
✓ An interface in java is a blueprint of a class. It has static final variables
and abstract methods.
✓ The interface in java is a mechanism to achieve abstraction. There
can be only abstract methods in the java interface that does not contain
method body. It is used to achieve abstraction and multiple inheritance in
Java.
✓ It cannot be instantiated just like abstract class.
✓ Interface fields are public, static and final by default, and methods are
public and abstract.
Interfaces

Why use Java interface?


Interfaces
How to declare an interface?

interface <interface_name>
{
// declare constant fields
// declare methods that abstract by default.
}
Understanding relationship between classes and interfaces

As shown in the figure given below, a class extends


another class, an interface extends another interface, but a
class implements an interface.
Example 1

In this example, Printable interface has only one method, its


implementation is provided in the Pgm1 class.

interface printable
{
void print();
}
class Pgm1 implements printable
{
public void print()
{
System.out.println("Hello");
}
}
Interfaces
class IntefacePgm1
{
public static void main(String args[])
{
Pgm1 obj = new Pgm1 ();
obj.print();
}
}

Output:

Hello
Example 2
//Implementation: by second user
//Interface declaration: by first user
Interface class Rectangle implements Drawable
{
Drawable public void draw()
{ {
void draw(); System.out.println("drawing rectangle");
} }
}

class Circle implements Drawable


{
public void draw()
{
System.out.println("drawing circle");
}
}
//Using interface: by third user
class TestInterface1
{
public static void main(String args[])
{
//In real scenario, object is provided by method e.g.
getDrawable()
Drawable d=new Circle();

d.draw();
}
}
Output:

drawing circle
Multiple inheritance in Java by interface
✓ If a class implements multiple interfaces, or an interface
extends multiple interfaces i.e. known as multiple inheritance.
Example

interface Printable
{
void print();
}

interface Showable
{
void show();
}
class Pgm2 implements Printable,Showable
{
public void print()
{
System.out.println("Hello");
}

public void show()


{
System.out.println("Welcome");
}
}
Class InterfaceDemo
{
public static void main(String args[])
{
Pgm2 obj = new
Pgm2 ();
obj.print();
obj.show();
}
}

Output:
Hello
Welcome
Multiple inheritance is not supported through class in Java, but it is
possible by interface, why?

✓ As we have explained in the inheritance chapter, multiple inheritance is


not supported in case of class because of ambiguity.
✓ But it is supported in case of interface because there is no ambiguity as
implementation is provided by the implementation class. For example:
Example

interface Printable
{
void print();
}

interface Showable
{
void print();
}
class InterfacePgm1 implements Printable, Showable
{
public void print()
{
System.out.println("Hello");
}
} ✓ As you can see in the example
class InterfaceDemo
program, Printable and
{
public static void main(String args[]) Showable interface have same
{
methods, but its
InterfacePgm1 obj = new
InterfacePgm1 (); obj.print(); implementation is provided by
}
} class InterfacePgm1, so there

Output: is no ambiguity.

Hello
Interface inheritance
A class implements interface, but one interface extends another
interface .
interface Printable
void print();

{
}

interface Showable extends Printable


{
void show();
}
class InterfacePgm2 implements Showable
{
public void print()
{
System.out.println("Hello");
}
public void show()
{
System.out.println("Welcome");
}
Class InterfaceDemo2
{
public static void main(String args[])
{
InterfacePgm2 obj = new InterfacePgm2 ();
obj.print();
obj.show();
}
}
Output:

Hello Welcome
Program to implement Stack

public class StackDemo


{
private static final int
capacity = 3;
int arr[] = new int[capacity];
int top = -1;
Interfaces
public void push(int pushedElement)
{
if (top < capacity - 1)
{
top++;
arr[top] = pushedElement;
System.out.println("Element " + pushedElement + " is pushed to
Stack !");
Interfaces
printElements();
}
else
{
System.out.println("Stack Overflow !");
}
}
Interfaces
public void pop()
{
if (top >= 0)
{

}
else
{
Interfaces
top--;
}
System.out.println("Pop operation done !");
}

System.out.println("Stack Underflow !");

public void printElements()


{
if (top >= 0)
{
Interfaces
System.out.println("Elements in stack :");
for (int i = 0; i <= top; i++)
{
System.out.println(arr[i]);
}

}
}
Interfaces
class MyPgm
{

public static void main(String[] args)


{
StackDemo stackDemo = new StackDemo();

stackDemo.pop(); stackDemo.push(23); stackDemo.push(2);


stackDemo.push(73); stackDemo.push(21); stackDemo.pop();
stackDemo.pop();
Interfaces
Output

stackDemo.pop();
stackDemo.pop();
}
}
Chapter 2: Multi Threaded Programming
Q) What is Thread? Explain two ways of creation of thread in Java with
example.
A thread is a path of execution within a process.

• The Java Virtual Machine allows an application to have multiple


threads of execution running concurrently. Every thread has a
priority. Threads with higher priority are executed in preference to
threads with lower priority. Threads allows a program to operate
more efficiently by doing multiple things at the same time. Threads
can be used to perform complicated tasks in the background
without interrupting the main program.
Creating and Starting Threads

Creating a thread in Java is done like this:


Thread thread = new Thread();
To start the Java thread, you will call its start() method, like this:
thread. start();
This example doesn't specify any code for the thread to execute. Therefore, the
thread will stop again right away after it is started.

There are two ways to specify what code the thread should execute.
• The first is to create a subclass of Thread and override the run() method.
• The second method is to pass an object that implements Runnable (java.lang.
Runnable) to the Thread constructor.
The first way to specify what code a thread is to run, is to create a
subclass of Thread and override the run() method. The run() method is
what is executed by the thread after you call start(). Here is an example of
creating a Java Thread subclass:

public class MyThread extends Thread


{
public void run()
{
System.out.println("MyThread running");
}
}
To create and start the above thread you can do like this:

MyThread myThread = new MyThread();


myThread. start();

The start() call will return as soon as the thread is started.


It will not wait until the run() method is done. The run()
method will execute as if executed by a different CPU.
When the run() method executes it will print out the text
"MyThread running".
Java’s multithreading system is built upon the Thread class, its methods,
and its companion interface, Runnable.
The Thread class defines several methods that help manage threads
(shown below)
Creating a Thread

A thread can be created in two ways


1. we can implement the Runnable interface
2. we can extend the Thread class

1) Extending Threads: Thread creation by extending the Thread class

Constructor of Thread class:


• Thread();
• Thread ( string s);
• Thread (Runnable obj);
• Thread (Runnable obj, string s);
The first method 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.
If the class extends the Thread class, the thread can be run by creating an instance
of the class and call its start() method:
Extend : Example 1

class Multi extends Thread


{
public void run(){
System.out.println("thread is running...");
}
public static void main(String args[]){
Multi t1=new Multi();
t1.start();
}
}
Example : 2

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("Exiting child thread.");
}
}
class ExtendThread
{
public static void main(String args[])
In this program the child thread is
{ created by instantiating an object of
new NewThread(); // Create a new thread NewThread, which is derived from
try { Thread.
for(int i = 5;i>0;i--) Notice the call to super() inside
{ System.out.println("Main thread : " + i); NewThread. This invokes the
following form of the Thread
Thread.sleep(1000); constructor:
} public Thread (String threadName)
} threadName specifies the name of
catch (InterruptedException e) the thread.
{ System.out.println("Main thread Interrupted.");
}
System.out.println("Main thread exiting.");
}
}
2) Implementing Runnable : Thread creation by implementing runnable interface

The thread can also be created using runnable interface.


Implementing thread program using runnable interface is preferred
than implementing it by extending thread class because of the
following two reasons:

1. If a class extends a thread class, then it cannot extend any other class which
may be required to extend
2. If a class thread is extended, then all its functionalities get inherited. This is
an expensive operation.
Steps to create a thread by implementing Runnable interface,
• Create a class that implements the Runnable interface.
• After you create a class that implements Runnable, you will
instantiate an object of type Thread from within that class.

To implement Runnable, a class has to implement a single method


called run(), which is declared like this -
public void run()
• Inside run(), you will define the code that constitutes the new thread.
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 your program. This thread will
end when run() returns.
Example program -1

Differences between
class Multi3 implements Runnable
"extending" and
{
"implementing" Threads
public void run(){
System.out.println("thread is running...");
The major difference is that
}
when a class extends the
Thread class, you cannot
public static void main(String args[]){
extend any other class, but by
Multi3 m1=new Multi3();
implementing the Runnable
//Using the constructor Thread(Runnable r)
interface, it is possible to
Thread t1 =new Thread(m1);
extend from another class as
t1.start();
well, like: class MyClass
}
extends OtherClass
}
implements Runnable.
Example program -2

class NewThread implements Runnable catch (InterruptedException e)


{ Thread t; { System.out.println("Child Interrupted.");
NewThread() }
{ System.out.println("Exiting child thread.");
t = new Thread(this, "Demo Thread"); }
System.out.println("Child thread :" + t); }
t.start(); // start the thread
}
public void run()
{
try {
for (int i=5; i >0;i--)
{
System.out.println("child Thread:" + i);
Thread.sleep(500);
}
}
class ThreadDemo {
public static void main(String args[])
{ new NewThread();
Note:
try
In a multi-threaded program, often the
{
main thread must be the last thread to
for(int i=5;i>0;i--)
finish running.
{
In older JVMs, if the main thread finishes
System.out.println("Main Thread: " + i);
before a child thread has completed,
Thread.sleep(1000);
then the Java run-time system may
}
“hang”.
}
The above program ensures that the
catch (InterruptedException e)
main thread finished last, because the
{ System.out.println("Main thread interrupted.");
main thread sleeps for 1000
}
milliseconds between iterations, but the
System.out.println("Main thread exiting");
child sleeps for only 500 milliseconds.
}
This causes the child thread to terminate
}
earlier than the main thread.
Lifecycle and States of a Thread in Java

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:

1.New
2.Runnable
3.Blocked
4.Waiting
5.Timed Waiting
6.Terminated
Q) Lifecycle and States of a Thread in Java
The diagram shown below represent various states of a thread at any instant of time.
New Thread: When a new thread is created, it is in the new state. The thread has
not yet started to run when thread is in this state. When a thread lies in the new
state, it’s code is yet to be run and hasn’t started to execute.
Declaration: public static final Thread. State NEW

Runnable State: A thread that is ready to run is moved to runnable state. In this
state, a thread might actually be running or it might be ready to run at any instant of
time. It is the responsibility of the thread scheduler to give the thread, time to run.
Declaration: public static final Thread. State RUNNABLE

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 does not consume any
CPU cycle. Once the thread wait state is over or it is, it’s state is changed to RUNNABLE
and it’s moved back to thread pool.
Declaration: public static final Thread. State BLOCKED
Declaration: public static final Thread. State WAITING

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 a timed waiting state. Timed waiting threads and waiting threads cannot
use a processor, even if one is available.
Declaration: public static final Thread. State TIMED_WAITING
Terminated State: A thread terminates because of either of the following reasons:
• Because it exists normally. This happens when the code of thread has entirely
executed by the program.
• Because there occurred some unusual erroneous event, like segmentation fault or
an unhandled exception.

A thread that lies in a terminated state does no longer consumes any cycles of CPU.
A thread enters the TERMINATED state (sometimes called the dead state) when it
successfully completes its task or otherwise terminated due to any error or even it was
forcefully killed.

Declaration: public static final Thread. State TERMINATED


the following code example illustrates how to check state of a thread:

public class ThreadsInJava


{
The output of this public static void main(String[] args)
program will be, {
NEW Thread.State[] states = Thread.State.values();
RUNNABLE
BLOCKED
WAITING
for (Thread.State state : states)
TIMED_WAITING {
TERMINATED System.out.println(state);
}
}
}
Program for NEW state
A thread will be in this state before calling start() method.

public class JavaThreadLifeCycle


{
public static void main(String[] args)
{
Thread t = new Thread();

//Checking the state before starting the thread

System.out.println(t.getState()); //Output :
NEW
}
}
Program for RUNNABLE state
A thread will be in this state after calling the start() method.

public class JavaThreadLifeCycle


{
public static void main(String[] args)
{
Thread t = new Thread();

t.start();

//Checking the state after starting the thread

System.out.println(t.getState()); //Output : RUNNABLE


}}
Q) With an example program explain the usage of isAlive() and join() method

When we are using multiple threads in our application, we’ll create the
threads and call the start() method on these threads. It’s the Java
Virtual Machine that calls the run method of this thread when the
resources and CPU are ready. Then the thread will execute the run()
method and later transition to terminated state.

Suppose you have a scenario where you want to start further


processing only when a thread has ended then how will you know that
a thread has ended?

Java multi-threading provides two ways to find that–


• isAlive()
• join()
There are two ways to determine whether a thread has finished.

isAlive() method in Java


isAlive() method is the member of the Thread class and its general form is–
public final boolean isAlive()
isAlive() method tests if the thread it is called upon is alive or not. A thread is alive if it
has been started and not yet terminated. The isAlive() method returns true if the thread
upon which it is called is still running, otherwise it returns false.

join() method in Java


Join() method is used when you want to wait for the thread to finish. Its general form is–
public final void join() throws InterruptedException
This method waits until the thread on which it is called terminates. There are three
overloaded join functions.

• public final void join()- Waits indefinitely for this thread to die.
• public final void join(long millis)-Waits at most millis milliseconds for this thread to die. A
timeout of 0 means to wait forever.
• public final void join(long millis, int nanos)- Waits at most millis milliseconds plus nanos
nanoseconds for this thread to die.
Example program to demonstrate the use of isAlive():

public class JavaIsAliveExp extends Thread


{
public void run()
{
try
{
Thread.sleep(300);
System.out.println("is run() method isAlive "+Thread.currentThread().isAlive());
}
catch (InterruptedException e)
Output:
{
}
before starting thread isAlive: false
}
after starting thread isAlive: true
public static void main(String[] args)
is run() method isAlive true
{
JavaIsAliveExp t1 = new JavaIsAliveExp();
System.out.println("before starting thread isAlive: "+t1.isAlive());
t1.start();
System.out.println("after starting thread isAlive: "+t1.isAlive());
}
}
Example program to demonstrate the use of join():

public class Th extends Thread{


public void run()
{ th1.start();
for(int i=1;i<=4;i++) try
{ { Output:
try th1.join();
{ } 1
Thread.sleep(500); catch(Exception e) 2
} 3
{
catch(Exception e) 4
{ System.out.println(e);
1
System.out.println(e); } 1
} 2
System.out.println(i); th2.start(); 2
} th3.start(); 3
} } 3
public static void main(String args[]) } 4
{ 4
Th th1=new Th (); Here you can notice thread1 first complete its task, then
Th th2=new Th(); thread2 and thread3 will execute. Synchronization is not
Th th3=new Th(); performed here for access to the resource by th2 and th3.
Q) Define Synchronization? Explain how Synchronization is achieved in
JAVA?
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.
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 give 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 re-enter the same monitor if it so desires.
As Java implements synchronization through language elements, most of the
complexity associated with synchronization has been eliminated.
Two ways of synchronization:
We can synchronize code in two ways
1. Using synchronized methods
2. using synchronized statement/ Block

1.Using Synchronized Methods:

• Two invocations of synchronized methods cannot interleave on the same object.

• When one thread is executing a synchronized method for an object, all other threads
that invoke synchronized methods for the same object block (suspend execution) until
the first thread is done with the object.
Syntax: synchronized return-type method-name (parameter list);

Ex: Public synchronized void increment()


{
X++;
}
class Table
{
synchronized void printTable(int n)
{
System.out.println(“welcome to Synchronization program”);
for(int i=1;i<5;i++){
System.out.println(n*i);
try
{
Thread.sleep(400);
}
catch(Exception e)
{System.out.println(e);
}
}
}
System.out.println(“welcome to Synchronization program”);

}
class MyThread2 extends Thread
class MyThread1 extends Thread {
{ Table t;
Table t; // //reference to object of class Table MyThread2(Table t)
MyThread1(Table t) {
{ this.t=t;
this.t=t; }
} public void run()
public void run() {
{ t.printTable(100);
t.printTable(5); }
} }

you can see both Threads are accessing Print Resource. One thread writes something
and then goes to sleep. If synchronization is not implemented here, i.e. if the resource is
not restricted for access by only 1 thread at a time, then the Second Thread will awake
and write something in middle of access by the 1st thread. So this will go on and on until
termination and result in Data Issues.
public class TestSynchronization2
{ Output:
public static void main(String args[])
5
{ 10
Table obj = new Table(); //only one object 15
MyThread1 t1=new MyThread1(obj); 20
MyThread2 t2=new MyThread2(obj); 25
t1.start(); 100
t2.start(); 200
} 300
} 400
500
2.using synchronized statement/Block
Synchronized block can be used to perform synchronization on any specific resource of
the method.

Suppose we have 50 lines of code in our method, but we want to synchronize only 5
lines, in such cases, we can use synchronized block.

Synchronized statements must specify the object that provides the intrinsic lock:

The general form of the synchronized statement


public void run()
{
synchronized(p1) //synchronize statement. P1 here is an object of some class P
{
p1.display(s1);
}
}
class Table
{
void printTable(int n)
{
System.out.println(“welcome to Synchronization program”);
synchronized(this)
{ try
for(int i=1;i<=5;i++) {
{ Thread.sleep(400);
System.out.println(n*i); }
catch(Exception e)
{
System.out.println(e);
}
}
} // end of synchronized block
}
System.out.println(“End of Synchronized block”);
}
class MyThread2 extends Thread
class MyThread1 extends Thread {
{ Table t;
Table t; //reference to object of class Table MyThread2(Table t)
MyThread1(Table t) {
{ this.t=t;
this.t=t; }
} public void run()
public void run() {
{ t.printTable(100);
t.printTable(5); }
} }
}
public class TestSynchronizedBlock1
{
public static void main(String args[]) Output:
{
Table obj = new Table(); 5
//only one object 10
MyThread1 t1=new MyThread1(obj); 15
MyThread2 t2=new MyThread2(obj); 20
t1.start(); 25
100
t2.start();
200
} 300
} 400
500
Difference between using synchronized method & synchronized block
For synchronized methods, the lock will be held throughout the method
scope, while in the synchronized block, the lock is held only during that
block scope also known as critical section.

Synchronized block can throw NullPointerException if the expression


provided as parameter evaluates to null, which is not the case with
synchronized methods.

Synchronized block provides granular control over lock, as you can use
any lock to provide mutual exclusion to critical section code.
Synchronized method always lock either on current object or class level
lock, if its static synchronized method.
Producer Consumer Problem : Interthread Communication
Two or more threads communicate with each other by exchanging
the messages. This mechanism is called inter-thread communication.

In Producer-consumer problem, producer thread produces and the


consumer thread consumes whatever is produced. Both must work in
coordination to avoid wastage of CPU cycles. But there are certain
situations where the producer has to wait for the consumer to finish
consuming and similarly the consumer may need to wait for the
producer to produce the data.
Java supports interprocess communication mechanism via the
wait( ), notify( ), and notifyAll( ) methods.

•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( )
Following is an example program where 2 threads are created :
one for producer and another for consumer.

The producer thread produces (writes) the numbers from 0 to 9 and


the consumer thread consumes (reads) these numbers.

The wait () and notify() methods are used to send particular thread to
sleep or to resume the thread from sleep mode respectively.
Bounded Buffer Problem

• The bounded buffer problem is a classic problem in which there is a


buffer of n slots and each slot is capable of storing one unit of data.

• There are 2 processes running namely producer and consumer,


which are operating in the buffer.

• The producer inserts data in the buffer and Consumer deletes the
data from the buffer.
Thread priorities

Each thread have a priority. A thread can be created by


implementing the Runnable interface and overriding the run()
method. Then a Thread object can be created and the start()
method called.
The thread priority can be provided to the thread by the JVM or the
programmer. It determines when the processor is provided to the
thread as well as other resources.
The method setPriority() of class Thread can be used to set the
priority of the thread. Priorities are represented by a number
between 1 and 10. The getPriority() of class Thread can be used
to know the priority of the Thread
Thread class provides 3 constant properties:
public static int MIN_PRIORITY: It is the minimum priority of a thread. The value of it is
1.
public static int NORM_PRIORITY: It is the normal priority of a thread. The value of it is
5.
public static int MAX_PRIORITY: It is the maximum priority of a thread. The value of it
is 10.

We can also set the priority of thread between 1 to 10. This priority
is known as custom priority or user defined priority.
The value of level must be within the range MIN_PRIORITY and
MAX_PRIORITY. Currently, these values are 1 and 10,
respectively. To return a thread to default priority, specify
NORM_PRIORITY, which is currently 5. These priorities are
defined as static final variables within Thread.
You can obtain the current priority setting by calling the getPriority(
) method of Thread, shown here:
final int getPriority( )
Example 1: Maximum Priority Thread

public class JavaSetPriorityExp1 extends Thread


{
public void run()
{
System.out.println("Priority of thread is: "+Thread.currentThread().getPriority());
}
public static void main(String args[])
{
// creating one thread
JavaSetPriorityExp1 t1=new JavaSetPriorityExp1();
// print the maximum priority of this thread Output
t1.setPriority(Thread.MAX_PRIORITY); Priority of thread is: 10
// call the run() method
t1.start();
}
}
Example 1: Minimum Priority Thread

public class JavaSetPriorityExp2 extends Thread


{
public void run()
{
System.out.println("Priority of thread is: "+Thread.currentThread().getPriority());
}
public static void main(String args[])
{
// creating one thread
JavaSetPriorityExp2 t1=new JavaSetPriorityExp2(); Output
// print the maximum priority of this thread Priority of thread is: 1
t1.setPriority(Thread.MIN_PRIORITY);
// call the run() method
t1.start();
}
}
Write a Java program to create two threads, one thread displays “CMRIT” and the
other thread displays “BENGALURU” on the screen continuously.

class MyThread extends Thread


{
String str; public class ThreadSetA1
public MyThread(String s) { public static void main(String args[])
{ str=s; {
} MyThread t1= new MyThread("CMRIT");
public void run() MyThread t2= new MyThread("BENGALURU");
{ while(true) t1.start();
{ System.out.print(str + " "); t2.start(); }}
try
{ Thread.sleep(1000);
}
catch(InterruptedException ie)
{
System.out.println(ie.toString());
}
} }}
Question Bank
1. Why multiple inheritance is not possible in java, explain it.
2. Which is the alternative approach to implement multiple inheritance in
Java?
3. Define packages. Write a note how to import packages.
4. What is an interface? Write defining and implementing interface. Why
interface is need. Illustrate with an example the use of interface.
5. Explain different access specifiers in java with example.
6. Why is the “main” thread important? Write a Java program that creates
multiple child threads and also ensures that the main thread is the last
stop.
7. What do you mean by thread? Explain the different ways of creating
threads.
8.What is meant by multithreaded programming? Write a java program to create two
threads, one to display “computer “science” and another to display “electronics
communication” five times.
9.What is synchronization? Explain with an example, how synchronization is implemented
in Java.
10.What is the need of synchronization? How can synchronization be achieved in Java?
11.What is synchronization? Explain the role of synchronization with procedure and
consumer problem.
12.Describe the thread priority. How to assign and get thread priority. Explain with
programs
13.Explain how to create multiple threads in Java.
14.What is meant by isAlive() and join(). Write a program to illustrate isAlive() and join()
method.
15.List and define several threads which are available in Thread class.
16.Explain Various states of Thread along with program . Draw the lifecycle of Thread
17.Explain Producer consumer problem
18.Explain Bounded buffer problem

You might also like