// AccountDemo2.java // by Mark Weiss, Fall 2002 // Continues AccountDemo1, with monitors added. The withdraw() // method uses wait() to give up the processor (and monitor) until // a the deposit() method executes a notifyAll(). // Thus, an OverdraftException is avoided. class OverdraftException extends Exception { public OverdraftException( ) { } public OverdraftException( String msg ) { super( msg ); } } class Account { public void deposit( int d ) { synchronized( this ) { balance += d; System.out.println( "Deposited " + d ); // permits all waiting threads to be rescheduled: this.notifyAll( ); } } public void withdraw( int d ) throws OverdraftException { try { synchronized( this ) { // If wait() is called, this thread gives up the processor // and the monitor. It is suspended until notifyAll() is // executed by another thread: while( balance < d ) this.wait( ); balance -= d; System.out.println( "Withdrew " + d ); } } catch( InterruptedException e ) { throw new OverdraftException( "Interrupted " + d ); } } private int balance = 0; } class WithdrawThread extends Thread { private int amount; private Account acc; public WithdrawThread( Account a, int d ) { amount = d; acc = a; } public void run( ) { try { acc.withdraw( amount ); } catch( OverdraftException e ) { System.out.println( "Overdraft " + e.getMessage( ) ); } } } class DepositThread extends Thread { private int amount; private Account acc; public DepositThread( Account a, int d ) { amount = d; acc = a; } public void run( ) { acc.deposit( amount ); } } class AccountDemo2 { public static void main( String [] args ) { Account acc = new Account( ); Thread t1 = new WithdrawThread( acc, 100 ); Thread t2 = new WithdrawThread( acc, 75 ); Thread t3 = new WithdrawThread( acc, 25 ); Thread t4 = new DepositThread( acc, 200 ); t4.setPriority( Thread.MIN_PRIORITY ); t4.start( ); t1.start( ); t2.start( ); t3.start( ); } }