OOPS WITH JAVA BCS306A - Model Paper Solution
OOPS WITH JAVA BCS306A - Model Paper Solution
OOPS WITH JAVA BCS306A - Model Paper Solution
Identifiers:
Identifiers are used to name things, such as classes, variables, and methods. An
identifier may be any descriptive sequence of uppercase and lowercase letters, numbers,
or the underscore and dollar-sign characters. They must not begin with a number, lest
they be confused with a numeric literal. Again, Java is case-sensitive, so VALUE is a
different identifier than Value.
Literals:
A constant value in Java is created by using a literal representation of it. For
example, here are some literals:
100 98.6 ‗X‘ ―This is a test‖
Left to right, the first literal specifies an integer, the next is a floating-point value,
the third is a character constant, and the last is a string. A literal can be used anywhere
a value of its type is allowed.
Comments:
There are three types of comments defined by Java. You have already seen two:
single-line and multiline. The third type is called a documentation comment. This
type of comment is used to produce an HTML file that documents your program. The
documentation comment begins with a /** and ends with a */.
Separators:
In Java, there are a few characters that are used as separators. The most
commonly used separator in Java is the semicolon. As you have seen, it is often used to
terminate statements.
The separators are shown in the following table:
Solution:
Explain six lexical issues of Java 7 Marks
Scheme [7 = 7 Marks]
(b). Define Array. Write a Java program to implement the addition of two matrixes.
Answer: 7 Marks
An array is a group of like-typed variables that are referred to by a common
name. Arrays of any type can be created and may have one or more dimensions. A
specific element in an array is accessed by its index. Arrays offer a convenient means of
grouping related information.
int n;
int i, j;
Scanner in = null;
n = Integer.parseInt(args[0]);
try
{
in = new Scanner(System.in);
System.out.println("Size of the matrix is "+n);
// Declare the matrix
int a[][] = new int[n][n];
int b[][] = new int[n][n];
int c[][] = new int[n][n];
// Read the matrix A values
System.out.println("Enter the elements of the matrix A");
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
a[i][j] = in.nextInt();
// Read the matrix B values
System.out.println("Enter the elements of the matrix B");
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
b[i][j] = in.nextInt();
//Addition of 2 matrices
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
c[i][j] =a[i][j] + b[i][j];
} //end of j loop
}
// Display the elements of the matrix
System.out.println("Elements of resultant matrix are");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
System.out.print(c[i][j] + " ");
System.out.println();
}
}
catch (Exception e) {
}
finally
{
in.close();
}
}
}
Solution:
Define Array 1 Marks
Write a program to add 2 matrix 6 Marks
Scheme [1 + 6 = 7 Marks]
(c). Explain the following operations with examples. (i) << (ii) >> (iii)>>> 6 Marks
Answer:
The Left Shift (<<):
The left shift operator, <<, shifts all of the bits in a value to the left a specified number of
times. It has this general form:
value << num
Here, num specifies the number of positions to left-shift the value in value. That is, the
<< moves all of the bits in the specified value to the left by the number of bit
positions specified by num. For each shift left, the high-order bit is shifted out (and
lost), and a zero is brought in on the right. This means that when a left shift is applied to
an int operand, bits are lost once they are shifted past bit position 31. If the operand is a
long, then bits are lost after bit position 63.
The following code fragment demonstrates the >>>. Here, a is set to –1, which sets
all32 bits to 1 in binary. This value is then shifted right 24 bits, filling the top 24 bits
with zeros, ignoring normal sign extension. This sets a to 255.
int a = -1;
a = a >>> 24;
Solution:
Explain >>, <<, and >>> operators in detail 3 * 2 = 6 Marks
Scheme [6 = 6 Marks]
OR
2. (a). Explain object-oriented principles. 7 Marks
Answer:
All object-oriented programming languages provide mechanisms that help you
implement the object-oriented model. They are encapsulation, inheritance, and
polymorphism.
Encapsulation:
Encapsulation is the mechanism that binds together code and the data it
manipulates, and keeps both safe from outside interference and misuse. One way to
think about encapsulation is as a protective wrapper that prevents the code and data
from being arbitrarily accessed by other code defined outside the wrapper. Access to
the code and data inside the wrapper is tightly controlled through a well-defined
interface.
In Java, the basis of encapsulation is the class. A class defines the structure and
behavior (data and code) that will be shared by a set of objects. Each object of a given
class contains the structure and behavior defined by the class, as if it were stamped out
by a mold in the shape of the class. For this reason, objects are sometimes referred to as
instances of a class.
Inheritance:
Inheritance is the process by which one object acquires the properties of
another object. This is important because it supports the concept of hierarchical
classification.
For example, a Golden Retriever is part of the classification dog, which in turn is part
of the mammal class, which is under the larger class animal. Without the use of
hierarchies, each object would need to define all of its characteristics explicitly. However,
by use of inheritance, an object need only define those qualities that make it unique
within its class. It can inherit its general attributes from its parent. Thus, it is the
inheritance mechanism that makes it possible for one object to be a specific instance of a
more general case.
Polymorphism:
Polymorphism is a feature that allows one interface to be used for a general class of
actions. The specific action is determined by the exact nature of the situation.
Consider a stack (which is a last-in, first-out list). You might have a program that
requires three types of stacks. One stack is used for integer values, one for floating-point
values, and one for characters. The algorithm that implements each stack is the same,
even though the data being stored differs. In a non–object-oriented language, you would
be required to create three different sets of stack routines, with each set using different
names. However, because of polymorphism, in Java you can specify a general set of
stack routines that all share the same names.
Solution:
Explain the object oriented principals 7 Marks
Scheme [7 = 7 Marks]
(b). Write a Java program to sort the elements using a for loop. 7 Marks
Answer:
// Java Program to Sort Elements of an Array in Ascending Order
class Sorting
{
static int length;
public static void printArray(int[] array)
{
for (int i = 0; i < length; i++)
{
System.out.print(array[i] + " ");
}
System.out.println();
}
Nested ifs
A nested if is an if statement that is the target of another if or else. Nested ifs
are very common in programming. When you nest ifs, the main thing to remember is
that an else statement always refers to the nearest if statement that is within the same
block as the else and that is not already associated with an else. Here is an example:
if(i == 10)
{
if(j < 20)
a = b;
if(k > 100)
c = d; // this if is
else
a = c; // associated with this else
}
else a = d; // this else refers to if(i == 10)
The if-else-if Ladder
A common programming construct that is based upon a sequence of nested ifs is the if-
else-if ladder. It looks like this:
if(condition)
statement;
else if(condition)
statement;
else if(condition)
statement; . . .
else statement;
The if statements are executed from the top down. As soon as one of the conditions
controlling the if is true, the statement associated with that if is executed, and the rest
of the ladder is bypassed. If none of the conditions is true, then the final else statement
will be executed. The final else acts as a default condition; that is, if all other conditional
tests fail, then the last else statement is performed. If there is no final else and all other
conditions are false, then no action will take place.
Solution:
Explain different types of if statement 6 Marks
Scheme [6 = 6 Marks]
MODULE-2
3. (a). What are constructors? Explain two types of constructors with an example
program. 7 Marks
Answer:
Java allows objects to initialize themselves when they are created. This automatic
initialization is performed through the use of a constructor.
A constructor initializes an object immediately upon creation. It has the same
name as the class in which it resides and is syntactically similar to a method. Once
defined, the constructor is automatically called when the object is created, before the
new operator completes. Constructors look a little strange because they have no return
type, not even void. This is because the implicit return type of a class’ constructor is
the class type itself.
There are 2 types of constructor:
I. Simple Constructor
II. Parameterized Constructors
Simple Constructor:
Let‘s begin by defining a simple constructor that sets the dimensions of each box to the
same values. This version is shown here:
/* Here, Box uses a constructor to initialize the dimensions of a box. */
class Box
{
double width;
double height;
double depth;
Box()
{
System.out.println("Constructing Box");
width = 10;
height = 10;
depth = 10;
}
double volume()
{
return width * height * depth;
}
}
class Constructor
{
public static void main(String[] args)
{
Box mybox1 = new Box();
Box mybox2 = new Box();
double vol;
vol = mybox1.volume();
System.out.println("Volume is " + vol);
vol = mybox2.volume();
System.out.println("Volume is " + vol);
}
}
As you can see, both mybox1 and mybox2 were initialized by the Box( ) constructor when
they were created. Since the constructor gives all boxes the same dimensions, 10 by 10
by 10, both mybox1 and mybox2 will have the same volume.
When you allocate an object, you use the following general form:
class-var = new classname( );
What is actually happening is that the constructor for the class is being called. Thus, in
the line
Box mybox1 = new Box();
Parameterized Constructors
While the Box( ) constructor in the preceding example does initialize a Box
object, it is not very useful—all boxes have the same dimensions. What is needed is a
way to construct Box objects of various dimensions. The easy solution is to add
parameters to the constructor.
For example, the following version of Box defines a parameterized constructor that sets
the dimensions of a box as specified by those parameters. Pay special attention to how
Box objects are created.
/* Here, Box uses a parameterized constructor to initialize the dimensions of a box.
*/
class Box
{
double width;
double height;
double depth;
Box(double w, double h, double d)
{
width = w;
height = h;
depth = d;
}
double volume()
{
return width * height * depth;
}
}
class Constructor
{
public static void main(String[] args)
{
Box mybox1 = new Box(10, 20, 15);
Box mybox2 = new Box(3, 6, 9);
double vol;
vol = mybox1.volume();
System.out.println("Volume is " + vol);
vol = mybox2.volume();
System.out.println("Volume is " + vol);
}
}
Solution:
Define constructor 1 Marks
Explain two types of constructor 6 Marks
Scheme [1 + 6 = 7 Marks]
(b). Define recursion. Write a recursive program to find nth Fibonacci number.
Answer: 7 Marks
Java supports recursion. Recursion is the process of defining something in
terms of itself. As it relates to Java programming, recursion is the attribute that allows
a method to call itself. A method that calls itself is said to be recursive.
// Recursive implementation of Fibonacci series program in java
class Fibonacci
{
static int fib(int n)
{
if (n <= 1)
return n;
// Recursive call
return fib(n - 1) + fib(n - 2);
}
public static void main(String args[])
{
int N = 10;
for (int i = 0; i < N; i++)
{
System.out.print(fib(i) + " ");
}
}
}
Solution:
Define recursion 1 Marks
Write a program to find Fibonacci Series 6 Marks
Scheme [1 + 6 = 7 Marks]
// methods to access c
void setc(int i)
{
// set c's value
c = i;
}
int getc()
{
// get c's value
return c;
}
}
class AccessTest
{
public static void main(String[] args)
{
Test ob = new Test();
// These are OK, a and b may be accessed directly
ob.a = 10;
ob.b = 20;
// This is not OK and will cause an error
// ob.c = 100; // Error!
// You must access c through its methods
ob.setc(100); // OK
System.out.println("a, b, and c: " + ob.a + " " + ob.b + " " + ob.getc());
}
}
Inside the Test class, a uses default access, which for this example is the same as
specifying public. b is explicitly specified as public. Member c is given private access.
This means that it cannot be accessed by code outside of its class. So, inside the
AccessTest class, c cannot be used directly.
Call by Reference:
In this approach, a reference to an argument (not the value of the argument) is
passed to the parameter. Inside the subroutine, this reference is used to access the
actual argument specified in the call. This means that changes made to the
parameter will affect the argument used to call the subroutine.
When you pass this reference to a method, the parameter that receives it will
refer to the same object as that referred to by the argument. This effectively means
that objects act as if they are passed to methods by use of call-by-reference. Changes to
the object inside the method do affect the object used as an argument. For example,
consider the following program:
// Objects are passed through their references.
class Test
{
int a, b;
Test(int i, int j)
{
a = i;
b = j;
}
// pass an object
void meth(Test o)
{
o.a *= 2;
o.b /= 2;
}
}
class PassObjRef
{
public static void main(String[] args)
{
Test ob = new Test(15, 20);
System.out.println("ob.a and ob.b before call: " + ob.a + " " + ob.b);
ob.meth(ob);
System.out.println("ob.a and ob.b after call: " + ob.a + " " + ob.b);
}
}
This program generates the following output:
ob.a and ob.b before call: 15 20
ob.a and ob.b after call: 30 10
Solution:
Explain Call-by value and Call by reference 4 Marks
Write the example programs 3 Marks
Scheme [4 + 3 = 7 Marks]
(b). Write a program to perform Stack operations using proper class and Methods.
Answer: 7 Marks
// This class defines an integer stack that can hold 10 values.
class Stack
{
private int[] stck = new int[10];
private int tos;
Stack()
{
tos = -1;
}
void push(int item)
{
if(tos==9)
System.out.println("Stack is full.");
else
stck[++tos] = item;
}
int pop()
{
if(tos < 0)
{
System.out.println("Stack underflow.");
return 0;
}
else
return stck[tos--];
}
}
class TestStack
{
public static void main(String[] args)
{
Stack mystack = new Stack();
for(int i=0; i<10; i++)
mystack.push(i);
System.out.println("Stack in mystack:");
for(int i=0; i<10; i++)
System.out.println(mystack.pop());
}
}
Solution:
Write a program to implement stack operation 7 Marks
Scheme [7 = 7 Marks]
However, when a local variable has the same name as an instance variable, the local
variable hides the instance variable. This is why width, height, and depth were not
used as the names of the parameters to the Box( ) constructor inside the Box class. If
they had been, then width, for example, would have referred to the formal parameter,
hiding the instance variable width. While it is usually easier to simply use different
names, there is another way around this situation. Because this lets you refer directly to
the object, you can use it to resolve any namespace collisions that might occur between
instance variables and local variables.
For example, here is another version of Box( ), which uses width, height, and depth for
parameter names and then uses this to access the instance variables by the same name:
// Use this to resolve name-space collisions.
Box(double width, double height, double depth)
{
this.width = width;
this.height = height;
this.depth = depth;
}
Solution:
Explain use of this in Java with example. 6 Marks
Scheme [6 = 6 Marks]
MODULE-3
interface Interface2
{
void method2();
}
public class MyClass implements Interface1, Interface2
{
public void method1()
{
// implementation of method1
}
Example:
// Declare the interfaces
interface Walkable
{
void walk();
}
interface Swimmable
{
void swim();
}
// Implement the interfaces in a class
class Duck implements Walkable, Swimmable
{
public void walk()
{
System.out.println("Duck is walking.");
}
class B extends A
{
int k;
B(int a, int b, int c)
{
super(a, b);
k = c;
}
// display k – this overrides show() in A
void show()
{
System.out.println("k: " + k);
}
}
class Override
{
public static void main(String[] args)
{
B subOb = new B(1, 2, 3);
subOb.show(); // this calls show() in B
}
}
The output produced by this program is shown here:
k: 3
When show( ) is invoked on an object of type B, the version of show( ) defined within B
is used. That is, the version of show( ) inside B overrides the version declared in A.
If you wish to access the superclass version of an overridden method, you can do so by
using super. For example, in this version of B, the superclass version of show( ) is
invoked within the subclass‘ version. This allows all instance variables to be displayed.
class B extends A
{
int k;
B(int a, int b, int c)
{
super(a, b);
k = c;
}
void show()
{
super.show(); // this calls A's show()
System.out.println("k: " + k);
}
}
(b). What is the importance of the super keyword in inheritance? Illustrate with a
suitable example. 7 Marks
Answer:
Whenever a subclass needs to refer to its immediate superclass (When using
inheritance), it can do so by use of the keyword super.
super has two general forms. The first calls the superclass‘ constructor. The second is
used to access a member of the superclass that has been hidden by a member of a
subclass. Each use is examined here.
To see how super( ) is used, consider this improved version of the BoxWeight class:
// BoxWeight now uses super to initialize its Box attributes.
class BoxWeight extends Box
{
double weight; // weight of box
class B extends A
{
int i; // this i hides the i in A
B(int a, int b)
{
super.i = a; // i in A
i = b; // i in B
}
void show()
{
System.out.println("i in superclass: " + super.i);
System.out.println("i in subclass: " + i);
}
}
class UseSuper
{
public static void main(String[] args)
{
B subOb = new B(1, 2);
subOb.show();
}
}
Solution:
Explain the use of super in inheritance. 4 Marks
Write an example program. 3 Marks
Scheme [4 + 3 = 7 Marks]
(c). What is abstract class and abstract method? Explain with an example. 6 Marks
Answer:
To declare a class abstract, you simply use the abstract keyword in front of the class
keyword at the beginning of the class declaration. There can be no objects of an
abstract class. That is, an abstract class cannot be directly instantiated with the new
operator. Such objects would be useless, because an abstract class is not fully defined.
Also, you cannot declare abstract constructors, or abstract static methods. Any
subclass of an abstract class must either implement all of the abstract methods in
the superclass, or be declared abstract itself.
Here is a simple example of a class with an abstract method, followed by a class which
implements that method:
// A Simple demonstration of abstract.
abstract class A
{
abstract void callme();
// concrete methods are still allowed in abstract classes
void callmetoo()
{
System.out.println("This is a concrete method.");
}
}
class B extends A
{
void callme()
{
System.out.println("B's implementation of callme.");
}
}
class AbstractDemo
{
public static void main(String[] args)
{
B b = new B();
b.callme();
b.callmetoo();
}
}
Notice that no objects of class A are declared in the program. It is not possible to
instantiate an abstract class. One other point: class A implements a concrete method
called callmetoo( ). This is perfectly acceptable. Abstract classes can include as much
implementation as they see fit.
Although abstract classes cannot be used to instantiate objects, they can be used to
create object references, because Java‘s approach to run-time polymorphism is
implemented through the use of superclass references. Thus, it must be possible to
create a reference to an abstract class so that it can be used to point to a subclass object.
Solution:
Explain abstract class and abstract method with example. 6 Marks
Scheme [6 = 6 Marks]
MODULE-4
7. (a). Define package. Explain the steps involved in creating a user-defined package
with an example. 7 Marks
Answer:
Java provides a mechanism for partitioning the class name space into more
manageable chunks. This mechanism is the package. The package is both a naming
and a visibility control mechanism. You can define classes inside a package that are not
accessible by code outside that package.
You can also define class members that are exposed only to other members of the
same package. This allows your classes to have intimate knowledge of each other, but
not expose that knowledge to the rest of the world.
Define Package:
To create a package is quite easy: simply include a package command as the first
statement in a Java source file. Any classes declared within that file will belong to
the specified package. The package statement defines a name space in which
classes are stored.
If you omit the package statement, the class names are put into the default
package, which has no name. While the default package is fine for short, sample
programs, it is inadequate for real applications.
Most of the time, you will define a package for your code.
This is the general form of the package statement:
package pkg;
Here, pkg is the name of the package. For example, the following statement creates
a package called mypackage:
package mypackage;
Typically, Java uses file system directories to store packages.
Import Packages:
In a Java source file, import statements occur immediately following the package
statement (if it exists) and before any class definitions.
This is the general form of the import statement:
import pkg1 [.pkg2].(classname | *);
Here, pkg1 is the name of a top-level package, and pkg2 is the name of a
subordinate package inside the outer package separated by a dot (.).
There is no practical limit on the depth of a package hierarchy, except that
imposed by the file system.
Finally, you specify either an explicit classname or a star (*), which indicates that
the Java compiler should import the entire package.
Example Program:
/* Package mypackage */
package mypackage;
(c). Define an exception. What are the key terms used in exception handling?
Answer: 6 Marks
An exception is an abnormal condition that arises in a code sequence at run
time. In other words, an exception is a run-time error. A Java exception is an object
that describes an exceptional (that is, error) condition that has occurred in a piece of
code.
When an exceptional condition arises, an object representing that exception is created
and thrown in the method that caused the error. That method may choose to handle
the exception itself, or pass it on. Either way, at some point, the exception is caught and
processed.
Example Program:
/* Package mypackage */
package mypackage;
public class MyPackageClass
{
public void displayMessage()
{
System.out.println("Hello from MyPackageClass in mypack package!");
}
// New utility method
public static int addNumbers(int a, int b)
{
return a + b;
}
}
//Main program outside the mypackage folder
import mypackage.MyPackageClass;
//import mypackage.*;
public class PackageDemo
{
public static void main(String[] args)
{
// Creating an instance of MyPackageClass from the mypackage package
MyPackageClass myPackageObject = new MyPackageClass();
// Calling the displayMessage method from MyPackageClass
myPackageObject.displayMessage();
// Using the utility method addNumbers from MyPackageClass
int result = MyPackageClass.addNumbers(5, 3);
System.out.println("Result of adding numbers: " + result);
}
}
Solution:
Explain the concept of import package. 3 Mark
Write the example program 4 Marks
Scheme [3 + 4 = 7 Marks]
(b). How do you create your own exception class? Explain with a program. 7 Marks
Answer:
Although Java‘s built-in exceptions handle most common errors, you will probably
want to create your own exception types to handle situations specific to your
applications. This is quite easy to do: just define a subclass of Exception (which is, of
course, a subclass of Throwable). Your subclasses don‘t need to actually implement
anything—it is their existence in the type system that allows you to use them as
exceptions.
The Exception class does not define any methods of its own. It does, of course, inherit
those methods provided by Throwable. Thus, all exceptions, including those that you
create, have the methods defined by Throwable available to them. You may also wish to
override one or more of these methods in exception classes that you create.
Exception defines four public constructors. Two support chained exceptions,
described in the next section. The other two are shown here:
Exception( ) Exception(String msg)
The first form creates an exception that has no description. The second form lets you
specify a description of the exception.
Although specifying a description when an exception is created is often useful, sometimes
it is better to override toString( ). Here‘s why: The version of toString( ) defined by
Throwable (and inherited by Exception) first displays the name of the exception followed
by a colon, which is then followed by your description. By overriding toString( ), you can
prevent the exception name and colon from being displayed. This makes for a cleaner
output, which is desirable in some cases.
The following example declares a new subclass of Exception and then uses that subclass
to signal an error condition in a method. It overrides the toString( ) method, allowing a
carefully tailored description of the exception to be displayed.
// This program creates a custom exception type.
class MyException extends Exception
{
private int detail;
MyException(int a)
{
detail = a;
}
public String toString()
{
return "MyException[" + detail + "]";
}
}
class ExceptionDemo
{
static void compute(int a) throws MyException
{
System.out.println("Called compute(" + a + ")");
if(a > 10)
throw new MyException(a);
System.out.println("Normal exit");
}
public static void main(String[] args)
{
try
{
compute(1);
compute(20);
}
catch (MyException e)
{
System.out.println("Caught " + e);
}
}
}
Solution:
Explain how to create own exception. 4 Marks
Write an example program. 3 Marks
Scheme [4 + 3 = 7 Marks]
(c). Demonstrate the working of a nested try block with an example. 6 Marks
Answer:
The try statement can be nested. That is, a try statement can be inside the block of
another try. Each time a try statement is entered, the context of that exception is pushed on
the stack. If an inner try statement does not have a catch handler for a particular exception,
the stack is unwound and the next try statement’s catch handlers are inspected for a match.
This continues until one of the catch statements succeeds, or until all of the nested try
statements are exhausted.
If no catch statement matches, then the Java run-time system will handle the
exception. Here is an example that uses nested try statements:
// An example of nested try statements.
class NestTry
{
public static void main(String[] args)
{
try
{
int a = args.length;
/* If no command-line args are present, the following statement will
generate a divide-by-zero exception. */
int b = 42 / a;
System.out.println("a = " + a);
try
{
// nested try block
/* If one command-line arg is used, then a divide-by-zero exception will be
generated by the following code. */
if(a==1)
a = a/(a-a); // division by zero
/* If two command-line args are used, then generate an out-of-bounds
exception. */
if(a==2)
{
int[] c = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("Array index out-of-bounds: " + e);
}
}
catch(ArithmeticException e)
{
System.out.println("Divide by 0: " + e);
}
}
}
Solution:
Demonstrate the working of nested try block 6 Marks
Scheme [6 = 6 Marks]
MODULE-5
9. (a). What do you mean by a thread? Explain the different ways of creating
threads. 7 Marks
Answer:
Java provides built-in support for multithreaded programming. A multithreaded
program contains two or more parts that can run concurrently. Each part of such a program
is called a thread, and each thread defines a separate path of execution. Thus,
multithreading is a specialized form of multitasking.
In the most general sense, we create a thread by instantiating an object of type
Thread. Java defines two ways in which this can be accomplished:
1. You can implement the Runnable interface.
2. You can extend the Thread class, itself.
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. 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()
Inside run( ), you will define the code that constitutes the new thread. It is important to
understand that 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.
After you create a class that implements Runnable, you will instantiate an object of type
Thread from within that class. Thread defines several constructors. The one that we will use is
shown here:
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( ) initiates a call to run( ). The start( )
method is shown here:
void start( )
Here is an example that creates a new thread and starts it running:
// 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);
}
// 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 ThreadDemo
{
public static void main(String[] args)
{
NewThread nt = new NewThread(); // create a new thread
nt.t.start(); // Start the thread
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
Inside NewThread’s constructor, a new Thread object is created by the following statement:
t = new Thread(this, "Demo Thread");
Passing this as the first argument indicates that you want the new thread to call the run( )
method on this object. Inside main( ), start( ) is called, which starts the thread of execution
beginning at the run( ) method. This causes the child thread’s for loop to begin. Next the main
thread enters its for loop. Both threads continue running, sharing the CPU in single-core
systems, until their loops finish.
Extending Thread
The second way to create a thread is to create a new class that extends Thread, and then
to create an instance of that class. The extending class must override the run( ) method, which
is the entry point for the new thread. As before, a call to start( ) begins execution of the new
thread. Here is the preceding program rewritten to extend 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);
}
// 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)
{
NewThread nt = new NewThread(); // create a new thread
nt.start(); // start the thread
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e){
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
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.
Solution:
Explain two different implementation of threads with example 7 Marks
Scheme [7 = 7 Marks]
(c). Discuss values() and valueOf() methods in Enumerations with suitable examples.
Answer: 6 Marks
All enumerations automatically contain two predefined methods: values( ) and
valueOf( ). Their general forms are shown here:
public static enum-type [ ] values( ) public static enum-type valueOf(String str)
The values( ) method returns an array that contains a list of the enumeration constants.
The valueOf( ) method returns the enumeration constant whose value corresponds to the
string passed in str. In both cases, enum-type is the type of the enumeration. For
example, in the case of the Apple enumeration shown earlier, the return type of
Apple.valueOf("Winesap") is Winesap.
However, there are two distinct types of multitasking: process-based and thread-based.
It is important to understand the difference between the two. For many readers, process-
based multitasking is the more familiar form. A process is, in essence, a program that is
executing. Thus, process-based multitasking is the feature that allows your computer to run
two or more programs concurrently.
In a thread-based multitasking environment, the thread is the smallest unit of
dispatchable code. This means that a single program can perform two or more tasks
simultaneously. For instance, a text editor can format text at the same time that it is printing, as
long as these two actions are being performed by two separate 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);
}
public void run()
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println(name + "Interrupted");
}
System.out.println(name + " exiting.");
}
}
class MultiThreadDemo
{
public static void main(String[] args)
{
NewThread nt1 = new NewThread("One");
NewThread nt2 = new NewThread("Two");
NewThread nt3 = new NewThread("Three");
nt1.t.start();
nt2.t.start();
nt3.t.start();
try
{
Thread.sleep(10000);
}
catch (InterruptedException e)
{
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Solution:
Define multithreading. 2 Marks
Write a program to implement multithread programming. 5 Marks
Scheme [2 + 5 = 7 Marks]
Synchronization is easy in Java, because all objects have their own implicit monitor
associated with them. To enter an object‘s monitor, just call a method that has been
modified with the synchronized keyword. While a thread is inside a synchronized
method, all other threads that try to call it (or any other synchronized method) on the
same instance have to wait. To exit the monitor and relinquish control of the object to
the next waiting thread, the owner of the monitor simply returns from the synchronized
method.
Thread Communication:
// A correct implementation of a producer and consumer.
class Q
{
int n;
boolean valueSet = false;
synchronized int get()
{
while(!valueSet)
try {
wait();
}
catch(InterruptedException e)
{
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n)
{
while(valueSet)
try {
wait();
}
catch(InterruptedException e)
{
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
class Producer implements Runnable
{
Q q;
Thread t;
Producer(Q q)
{
this.q = q;
t = new Thread(this, "Producer");
}
public void run()
{
int i = 0;
while(true)
{
q.put(i++);
}
}
}
class Consumer implements Runnable
{
Q q;
Thread t;
Consumer(Q q)
{
this.q = q;
t = new Thread(this, "Consumer");
}
public void run()
{
while(true)
{
q.get();
}
}
}
class PCFixed
{
public static void main(String[] args)
{
Q q = new Q();
Producer p = new Producer(q);
Consumer c = new Consumer(q);
p.t.start();
c.t.start();
System.out.println("Press Control-C to stop.");
}
}
Solution:
Explain access matrix with its implmentation 6 Marks
Scheme [6 = 6 Marks]
GOOD LUCK