BankExampleWithoutDatabase.java
package examples;
import java.util.*;
public class BankExampleWithoutDatabase
{
private static final int NUM_ACCOUNTS = 10;
private static final int NUM_REPORTS = 10;
private static final int NUM_DEPOSITS = 10;
private static final int NUM_TRANSFERS = 10;
private static final int NUM_DEPOSIT_THREADS = 5;
private static final int NUM_TRANSFER_THREADS = 5;
private static final int NUM_REPORT_THREADS = 10;
private static final int INITIAL_BALANCE = 100;
private static final int AMOUNT_TO_DEPOSIT = 10;
private static final int AMOUNT_TO_TRANSFER = 20;
private Map accounts;
public BankExampleWithoutDatabase()
{
accounts = new HashMap();
for( int i = 0; i < NUM_ACCOUNTS; i++ )
openAccount( i, INITIAL_BALANCE );
}
private Thread createDepositThread( final double depositAmount )
{
Thread thread = new Thread( new Runnable() {
public void run()
{
for( int acctNumber = 0; acctNumber < NUM_ACCOUNTS; acctNumber++ )
{
Account acct = (Account)lookupAccount( acctNumber );
for( int i = 0; i < NUM_DEPOSITS; i++ )
{
deposit( acct, depositAmount ); }
}
}
} );
return thread;
}
private Thread createReportThread()
{
Thread thread = new Thread( new Runnable() {
public void run()
{
for( int i = 0; i < NUM_REPORTS; i++ )
{
generateReport(); }
}
} );
return thread;
}
private Thread createTransferThread( final double transferAmount )
{
Thread thread = new Thread( new Runnable() {
public void run()
{
for( int acctNumber = 0; acctNumber < NUM_ACCOUNTS; acctNumber++ )
{
Account fromAcct = lookupAccount( acctNumber );
Account toAcct = lookupAccount( ( acctNumber + 1 ) % NUM_ACCOUNTS );
for( int i = 0; i < NUM_TRANSFERS; i++ )
{
transfer( fromAcct, toAcct, transferAmount ); }
}
}
} );
return thread;
}
private synchronized void deposit( Account acct, double amount )
{
double balance = acct.getBalance(); balance += amount; acct.setBalance( balance ); }
private synchronized void generateReport()
{
int numAccounts = accounts.size(); double total = 0;
Collection values = accounts.values();
Iterator acctIterator = values.iterator();
while( acctIterator.hasNext() )
{
Account account = (Account)acctIterator.next();
double balance = account.getBalance(); total += balance; }
System.err.println( total + " for " + numAccounts + " accounts " );
}
private synchronized Account lookupAccount( int accountNumber )
{
Object key = new Integer( accountNumber );
return (Account)accounts.get( key ); }
public static void main(String[] args) throws InterruptedException
{
BankExampleWithoutDatabase example = new BankExampleWithoutDatabase();
example.run();
}
private synchronized Account openAccount( int accountNumber, double initialBalance )
{
Account account = new DefaultAccount();
Object key = new Integer( accountNumber );
accounts.put( key, account );
account.setBalance( initialBalance );
return account;
}
public void run() throws InterruptedException
{
int numThreads = NUM_DEPOSIT_THREADS + NUM_TRANSFER_THREADS + NUM_REPORT_THREADS;
Thread[] threads = new Thread[numThreads];
int index = 0;
for( int i = 0; i < NUM_DEPOSIT_THREADS; i++ )
threads[index++] = createDepositThread( AMOUNT_TO_DEPOSIT );
for( int i = 0; i < NUM_TRANSFER_THREADS; i++ )
threads[index++] = createTransferThread( AMOUNT_TO_TRANSFER );
for( int i = 0; i < NUM_REPORT_THREADS; i++ )
threads[index++] = createReportThread();
for( int i = 0; i < threads.length; i++ )
threads[i].start();
for( int i = 0; i < threads.length; i++ )
threads[i].join();
double expectedBalance = INITIAL_BALANCE + NUM_DEPOSIT_THREADS * NUM_DEPOSITS * AMOUNT_TO_DEPOSIT;
for( int i = 0; i < NUM_ACCOUNTS; i++ )
{
Account acct = lookupAccount( i );
double balance = acct.getBalance();
assert balance == expectedBalance : "Incorrect balance for account " + i + ": " + balance;
}
}
private synchronized void transfer( Account fromAcct, Account toAcct, double amount )
{
deposit( fromAcct, -amount ); deposit( toAcct, amount ); }
}