public StackImpl (int capacity) { stackArray = new Object[ capacity ]; }
public synchronized Object pop()
{
System.out.println(
Thread.currentThread() + ": popping" );
while ( isEmpty()
)
{
try
{
System.out.println( Thread.currentThread() + ": waiting to pop" );
wait();
}
catch ( InterruptedException e )
{ }
}
Object obj =
stackArray[
topOfStack ];
stackArray[
topOfStack--
] = null;
System.out.println(
Thread.currentThread() + ": notifying after pop" );
notify();
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();
}
catch (InterruptedException e )
{ }
}
stackArray[
++topOfStack
] = element;
System.out.println(
Thread.currentThread() + ": notifying after push" );
notify();
}
public boolean isFull() { return topOfStack == stackArray.length -1; }
public boolean isEmpty()
{
return topOfStack
< 0;
}
}
abstract class StackUser extends Thread
{
protected StackImpl stack;
public StackUser( String threadName,
StackImpl
aStack )
{
super( threadName
);
stack = aStack;
System.out.println(
this );
setDaemon( true );
// Daemon thread: dies no later than parent
start();
}
}
class StackPopper extends StackUser
{
public StackPopper( String threadName,
StackImpl
aStack )
{
super( threadName,
aStack );
}
public void run()
{
while (true)
{
stack.pop();
}
}
}
class StackPusher extends StackUser
{
public StackPusher( String threadName,
StackImpl
aStack )
{
super( threadName,
aStack );
}
public void run()
{
while (true)
{
stack.push(new Integer(1));
}
}
}
public class WaitAndNotifyTest
{
public static void main( String args[] )
throws InterruptedException
{
StackImpl stack
= new StackImpl( 5 );
new StackPusher(
"A",
stack
);
new StackPusher(
"B",
stack );
new StackPopper(
"C",
stack );
System.out.println(
"Main Thread sleeping." );
Thread.sleep( 200
);
System.out.println(
"Exit from Main Thread." );
}
}