A
ankur
This code defines 3 threads A, B and C as Daemon threads. However they
continue to push and pop on the Stack even after the main thread (user
thread) has died. How is that possible ? Because Daemon threads exist
only so long as user threads exist..isn't it ?
package pack4;
class StackImpl1 {
private Object[] stackArray;
private volatile int topOfStack;
StackImpl1 (int capacity) {
stackArray = new Object[capacity];
topOfStack = -1;
}
public synchronized Object pop() {
System.out.println(Thread.currentThread() + ": popping");
while (isEmpty())
try {
System.out.println(Thread.currentThread() + ": waiting
to pop");
wait(); // (1)
} catch (InterruptedException e) { }
Object obj = stackArray[topOfStack];
stackArray[topOfStack--] = null;
System.out.println(Thread.currentThread() + ": notifying after
pop");
notify(); // (2)
return obj;
}
public synchronized void push(Object element) {
System.out.println(Thread.currentThread() + ": pushing");
while (isFull())
try {
System.out.println(Thread.currentThread() + ": waiting
to push");
wait(); // (3)
} catch (InterruptedException e) { }
stackArray[++topOfStack] = element;
System.out.println(Thread.currentThread() + ": notifying after
push");
notify(); // (4)
}
public boolean isFull() { return topOfStack >= stackArray.length
-1; }
public boolean isEmpty() { return topOfStack < 0; }
}
abstract class StackUser extends Thread { // (5) Stack user
protected StackImpl1 stack; // (6)
StackUser(String threadName, StackImpl1 stack) {
super(threadName);
this.stack = stack;
System.out.println(this);
setDaemon(true); // (7) Daemon
thread
start(); // (8) Start this
thread
}
}
class StackPopper extends StackUser { // (9) Popper
StackPopper(String threadName, StackImpl1 stack) {
super(threadName, stack);
}
public void run() { while (true) stack.pop(); }
}
class StackPusher extends StackUser { // (10) Pusher
StackPusher(String threadName, StackImpl1 stack) {
super(threadName, stack);
}
public void run() { while (true) stack.push(new Integer(1)); }
}
public class WaitAndNotifyClient {
public static void main(String[] args)
throws InterruptedException { // (11)
StackImpl1 stack = new StackImpl1(5);
new StackPusher("A", stack);
new StackPusher("B", stack);
new StackPopper("C", stack);
System.out.println("Main Thread sleeping.");
Thread.sleep(10);
System.out.println("Exit from Main Thread.");
}
}
Output : Observe that the pushing and popping continues even after the
main thread has exited !
Thread[A,5,main]
Thread[B,5,main]
Thread[C,5,main]
Main Thread sleeping.
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Exit from Main Thread.---------------------------------------------
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: waiting to pop
Thread[B,5,main]: notifying after push
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: waiting to pop
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[A,5,main]: pushing
Thread[A,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[A,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
continue to push and pop on the Stack even after the main thread (user
thread) has died. How is that possible ? Because Daemon threads exist
only so long as user threads exist..isn't it ?
package pack4;
class StackImpl1 {
private Object[] stackArray;
private volatile int topOfStack;
StackImpl1 (int capacity) {
stackArray = new Object[capacity];
topOfStack = -1;
}
public synchronized Object pop() {
System.out.println(Thread.currentThread() + ": popping");
while (isEmpty())
try {
System.out.println(Thread.currentThread() + ": waiting
to pop");
wait(); // (1)
} catch (InterruptedException e) { }
Object obj = stackArray[topOfStack];
stackArray[topOfStack--] = null;
System.out.println(Thread.currentThread() + ": notifying after
pop");
notify(); // (2)
return obj;
}
public synchronized void push(Object element) {
System.out.println(Thread.currentThread() + ": pushing");
while (isFull())
try {
System.out.println(Thread.currentThread() + ": waiting
to push");
wait(); // (3)
} catch (InterruptedException e) { }
stackArray[++topOfStack] = element;
System.out.println(Thread.currentThread() + ": notifying after
push");
notify(); // (4)
}
public boolean isFull() { return topOfStack >= stackArray.length
-1; }
public boolean isEmpty() { return topOfStack < 0; }
}
abstract class StackUser extends Thread { // (5) Stack user
protected StackImpl1 stack; // (6)
StackUser(String threadName, StackImpl1 stack) {
super(threadName);
this.stack = stack;
System.out.println(this);
setDaemon(true); // (7) Daemon
thread
start(); // (8) Start this
thread
}
}
class StackPopper extends StackUser { // (9) Popper
StackPopper(String threadName, StackImpl1 stack) {
super(threadName, stack);
}
public void run() { while (true) stack.pop(); }
}
class StackPusher extends StackUser { // (10) Pusher
StackPusher(String threadName, StackImpl1 stack) {
super(threadName, stack);
}
public void run() { while (true) stack.push(new Integer(1)); }
}
public class WaitAndNotifyClient {
public static void main(String[] args)
throws InterruptedException { // (11)
StackImpl1 stack = new StackImpl1(5);
new StackPusher("A", stack);
new StackPusher("B", stack);
new StackPopper("C", stack);
System.out.println("Main Thread sleeping.");
Thread.sleep(10);
System.out.println("Exit from Main Thread.");
}
}
Output : Observe that the pushing and popping continues even after the
main thread has exited !
Thread[A,5,main]
Thread[B,5,main]
Thread[C,5,main]
Main Thread sleeping.
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Exit from Main Thread.---------------------------------------------
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: waiting to pop
Thread[B,5,main]: notifying after push
Thread[C,5,main]: notifying after pop
Thread[C,5,main]: popping
Thread[C,5,main]: waiting to pop
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: notifying after push
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: pushing
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[A,5,main]: pushing
Thread[A,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[B,5,main]: notifying after push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[A,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop