OOC Module 4
OOC Module 4
MODULE:IV
Packages in JAVA
There are many built-in packages such as java, lang, awt, javax, swing, net, io, util, sql
etc.
1) Java package is used to categorize the classes and interfaces so that they can be easily
maintained.
//save as Simple.java
package mypack;
public class Simple
{
public static void main(String args[])
{
System.out.println("Welcome to package");
}
}
How to access package from another package?
There are three ways to access the package from outside the package.
1. import package.*;
2. import package.classname;
3. fully qualified name.
1
Dept. of CSE, BGMIT OOC (Module 4)
18CS45
1) Using packagename.*
If you use package.* then all the classes and interfaces of this package will be
accessible but not subpackages.
The import keyword is used to make the classes and interface of another package accessible
to the current package.
//save by B.java
package
mypack; import
pack.*;
class B
{
public static void main(String args[])
{
A obj = new A();
obj.msg();
}
}
Output:Hello
2) Using packagename.classname
If you import package.classname then only declared class of this package will be
accessible.
//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
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.
//save by B.java
package
mypack; class B
{
public static void main(String args[])
3
Dept. of CSE, BGMIT OOC (Module 4)
18CS45
{
pack.A obj = new pack.A();//using fully qualified name
obj.msg();
}
}
Output:Hello
Access Modifiers/Specifiers
The access modifiers in java specify accessibility (scope) of a data member, method,
constructor or class.
1. private
2. default
3. protected
4. public
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.
4
Dept. of CSE, BGMIT OOC (Module 4)
18CS45
Interface in java
There are mainly three reasons to use interface. They are given below.
As shown in the figure given below, a class extends another class, an interface
extends another interface but a class implements an interface.
5
Dept. of CSE, BGMIT OOC (Module 4)
18CS45
Example 1
In this example, Printable interface has only one method, its implementation is
provided in the Pgm1 class.
interface printable
{
void print();
}
class IntefacePgm1
{
public static void main(String args[])
{
Pgm1 obj = new Pgm1
(); obj.print();
}
}
6
Dept. of CSE, BGMIT OOC (Module 4)
18CS45
Output:
Hello
Example 2
In this example, Drawable interface has only one method. Its implementation is provided
by Rectangle and Circle classes. In real scenario, interface is defined by someone but
implementation is provided by different implementation providers. And, it is used by
someone else. The implementation part is hidden by the user which uses the interface.
//Interface declaration: by first user
interface Drawable
{
void draw();
}
//Implementation: by second user
d.draw();
}
}
7
Dept. of CSE, BGMIT OOC (Module 4)
18CS45
Output:
drawing circle
Example
interface Printable
{
void print();
}
interface Showable
{
void show();
}
}
}
Class InterfaceDemo
{
public static void main(String args[])
{
Pgm2 obj = new Pgm2 ();
obj.print();
obj.show();
}
}
Output:
Hello
Welcome
Example
interface Printable
{
void print();
}
interface Showable
{
void print();
}
9
Dept. of CSE, BGMIT OOC (Module 4)
18CS45
class InterfaceDemo
{
public static void main(String args[])
{
InterfacePgm1 obj = new InterfacePgm1
(); obj.print();
}
}
Output:
Hello
As you can see in the above example, Printable and Showable interface have same
methods but its implementation is provided by class TestTnterface1, so there is no
ambiguity.
Interface inheritance
A class implements interface but one interface extends another interface . interface
Printable
{
void print();
}
Class InterfaceDemo2
{
public static void main(String args[])
{
InterfacePgm2 obj = new InterfacePgm2 ();
obj.print();
10
Dept. of CSE, BGMIT OOC (Module 4)
obj.show();
}
}
Output:
Hello Welcome
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)
When a Java program starts up, one thread begins running immediately. This is usually called the
main thread of your program, because it is the one that is executed when your program begins.
The main thread is important for two reasons:
• It is the thread from which other “child” threads will be spawned.
• Often, it must be the last thread to finish execution because it performs various shutdown
actions.
Although the main thread is created automatically when your program is started, it can be
controlled through a Thread object. To do so, you must obtain a reference to it by calling the
method currentThread( ), which is a public static member of Thread. Its general form is
Dept. of CSE, BGMIT OOC (Module 4)
shown here:
static Thread currentThread( )
Example:
In this program, a reference to the current thread (the main thread, in this case) is
obtained by calling currentThread( ), and this reference is stored in the local variable t.
Next, the program displays information about the thread. The program then calls
setName( ) to change the internal name of the thread. Information about the thread is
then redisplayed.
Next, a loop counts down from five, pausing one second between each line.
The pause is accomplished by the sleep( ) method. The argument to sleep( ) specifies the
delay period in milliseconds.
Output:
The number of milliseconds to suspend is specified in milliseconds. This method may throw an
InterruptedException.
Creating a Thread
There are two different ways to create threads.
Implementing Runnable
The easiest way to create a thread is to create a class that implements the Runnable interface.
You 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 like this:
public void run( )
run( ) establishes the entry point for another, concurrent thread of execution within your
program. This thread will end when run( ) returns.
Thread defines several constructors.
Thread(Runnable threadOb, String threadName)
In this constructor, threadOb is an instance of a class that implements the Runnable interface.
This defines where execution of the thread will begin. The name of the new thread is specified
by threadName.
After the new thread is created, it will not start running until you call its start( ) method, which
is declared within Thread. In essence, start( ) executes a call to run( ). The start( ) method is
shown here:
void start( )
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
Output:
The second way to create a thread is to create a new class that extends Thread, and then to
create an instance of that class. 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.
Example:
The child thread is created by instantiating an object of NewThread, which is derived from
Thread.
Notice the call to super( ) inside NewThread. This invokes the following form of the Thread
constructor:
public Thread(String threadName)
Here, threadName specifies the name of the thread.
Creating Multiple Threads
For example, the following program creates three child threads:
Dept. of CSE, BGMIT OOC (Module 4)
Dept. of CSE, BGMIT OOC (Module 4)
As you can see, once started, all three child threads share the CPU. Notice the call to
sleep(10000) in main( ). This causes the main thread to sleep for ten seconds and ensures that it
will finish last.
Thread Priorities
Thread priorities are used by the thread scheduler to decide when each thread should be allowed
to run. In theory, higher-priority threads get more CPU time than lower-priority threads. In
practice, the amount of CPU time that a thread gets often depends on several factors besides its
priority.
To set a thread’s priority, use the setPriority( ) method, which is a member of Thread.
This is its general form:
final void setPriority(int level)
Here, level specifies the new priority setting for the calling thread. 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( )
Synchronization
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 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.
Using Synchronized Methods
To enter an object’s monitor, just call a method that has been modified with the synchronized
keyword. While a thread is inside a synchronized method, all other threads that try to call it (or
any other synchronized method) on the same instance have to wait. To exit the monitor and
relinquish control of the object to the next waiting thread, the owner of the monitor simply
returns from the synchronized method.
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. The interesting thing to notice is that after call( ) prints
the opening bracket and the msg string, it calls Thread.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 target instance 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.
To fix the preceding program, you must serialize access to call( ). That is, you must restrict its
access to only one thread at a time. To do this, you simply need to precede call( )’s definition
with the keyword synchronized, as shown here:
class Callme {
synchronized void call(String msg) {
...
After
synchronized has been added to call( ), the output of the program is as follows:
[Hello]
[Synchronized]
[World]
The synchronized Statement
You 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.
Here is an alternative version of the preceding example, using a synchronized block within the
run( ) method:
Dept. of CSE, BGMIT OOC (Module 4)
Dept. of CSE, BGMIT OOC (Module 4)
Interthread Communication
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( )
The following sample program that incorrectly implements a simple form of the producer/
consumer problem. It consists of four classes: Q, the queue that you’re trying to synchronize;
Producer, the threaded object that is producing queue entries; Consumer, the threaded object
that is consuming queue entries; and PC, the tiny class that creates the single Q, Producer, and
Consumer.