1.
What
do you mean by subclass constructor method?
If your method overrides one of its superclass's
methods, you can invoke the overridden method through the use of the keyword
super
. You can
also use super
to refer to a hidden field (although hiding fields is discouraged). Consider
this class, Superclass
:
public class Superclass {
public void printMethod() {
System.out.println("Printed in Superclass.");
}
}
Here is a subclass, called
Subclass
, that
overrides printMethod()
:
public class Subclass extends Superclass {
// overrides printMethod in Superclass
public void printMethod() {
super.printMethod();
System.out.println("Printed in Subclass");
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
}
Within
Subclass
, the simple name printMethod()
refers to the one declared in Subclass
, which overrides the one in Superclass
.
So, to refer to printMethod()
inherited from Superclass
,
Subclass
must use a qualified name, using super
as shown. Compiling and executing
Subclass
prints the following:
Printed in Superclass.
Printed in Subclass
2.
Describe
Inter-thread communication.
- The communication between one thread to another thread is called inter-thread communication
We can achieve this by using
- wait()
- notify()
- notifyAll() Methods
We have a classic 'Producer-Consumer' problem
to explain the use of Inter-Thread communications in java,where one thread is
producing some data and another is consuming it .The producer has to wait until
the consumer is finished before it generates more data.
Let us start with an incorrect implementation of Producer-Consumer problem, where we are just using the mercy of synchronized method .
// An incorrect implementation of a producer and consumer.
class Q {
int n;
synchronized int get() {
System.out.println("Got: " + n);
return n;
}
synchronized void put(int n) {
this.n = n;
System.out.println("Put: " + n);
}
}
class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while (true) {
q.put(++i);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while (true) {
q.get();
}
}
}
public class Main {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
}
}
Although the put( ) and get( ) methods on Q are synchronized, nothing stops the producer from producing more things than the consumer can use and nothing stops the consumer from using the same product more than once.
Thus,you will get a wrong output as shown below.
Put: 1
Got: 1 Got: 1
Got: 1
Put: 2
Put: 3
Put: 4
Put: 5
Put: 6
Let us start with an incorrect implementation of Producer-Consumer problem, where we are just using the mercy of synchronized method .
// An incorrect implementation of a producer and consumer.
class Q {
int n;
synchronized int get() {
System.out.println("Got: " + n);
return n;
}
synchronized void put(int n) {
this.n = n;
System.out.println("Put: " + n);
}
}
class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while (true) {
q.put(++i);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while (true) {
q.get();
}
}
}
public class Main {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
}
}
Although the put( ) and get( ) methods on Q are synchronized, nothing stops the producer from producing more things than the consumer can use and nothing stops the consumer from using the same product more than once.
Thus,you will get a wrong output as shown below.
Put: 1
Got: 1 Got: 1
Got: 1
Put: 2
Put: 3
Put: 4
Put: 5
Put: 6
Got: 6
Here Consumer used the same product, product-1 thrice and Consumer didn't get a chance to use the products, Product-2,Product-3,Product-4 and Product-5.
Now we came to know that ,with the only use of synchronized, can't do proper communication between multiple threads.Don't worry ,java is rich enough to provide a solution for this issue,providing three methods ,wait(),notify() and notifyAll() for Inter-Thread Communication.
Let us try the Producer-Consumer problem with the wait() and notify() methods.
// A correct implementation of a producer and consumer.
class Q {
int n;
boolean isQueueEmpty = true;
synchronized int get() {
if (isQueueEmpty)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
isQueueEmpty = true;
notify();
return n;
}
synchronized void put(int n) {
if (!isQueueEmpty)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
isQueueEmpty = false;
System.out.println("Put: " + n);
notify();
}
}
class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while (true) {
q.get();
}
}
}
public class Main {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
}
}
Here you will get the expected result as shown below
Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5
We can see that Producer is not overrunning the Consumer and the Consumer is not using the same product twice.
Here Consumer used the same product, product-1 thrice and Consumer didn't get a chance to use the products, Product-2,Product-3,Product-4 and Product-5.
Now we came to know that ,with the only use of synchronized, can't do proper communication between multiple threads.Don't worry ,java is rich enough to provide a solution for this issue,providing three methods ,wait(),notify() and notifyAll() for Inter-Thread Communication.
Let us try the Producer-Consumer problem with the wait() and notify() methods.
// A correct implementation of a producer and consumer.
class Q {
int n;
boolean isQueueEmpty = true;
synchronized int get() {
if (isQueueEmpty)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
isQueueEmpty = true;
notify();
return n;
}
synchronized void put(int n) {
if (!isQueueEmpty)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
isQueueEmpty = false;
System.out.println("Put: " + n);
notify();
}
}
class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while (true) {
q.get();
}
}
}
public class Main {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
}
}
Here you will get the expected result as shown below
Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5
We can see that Producer is not overrunning the Consumer and the Consumer is not using the same product twice.
No comments:
Post a Comment