In: Computer Science
Problem: Add a condition to the deposit method of the BankAccount class, restricting deposits to $100,000 (the insurance limit of the U.S. government). The method should block until sufficient money has been withdrawn by another thread. Test your program with a large number of deposit threads. (All other classes are provided below)
Bank Account.java (This class is the one that needs to be modified)
/**
A bank account has a balance that can be changed by
deposits and withdrawals.
*/
public class BankAccount
{
private double balance;
/**
Constructs a bank account with a zero balance.
*/
public BankAccount()
{
balance = 0;
}
/**
Deposits money into the bank account.
@param amount the amount to deposit
*/
public void deposit(double amount)
{
System.out.print("Depositing " + amount);
double newBalance = balance + amount;
System.out.println(", new balance is " + newBalance);
balance = newBalance;
}
/**
Withdraws money from the bank account.
@param amount the amount to withdraw
*/
public void withdraw(double amount)
{
System.out.print("Withdrawing " + amount);
double newBalance = balance - amount;
System.out.println(", new balance is " + newBalance);
balance = newBalance;
}
/**
Gets the current balance of the bank account.
@return the current balance
*/
public double getBalance()
{
return balance;
}
}
Bank Account ThreadRunner.java
/**
This program runs threads that deposit and withdraw
money from the same bank account.
*/
public class BankAccountThreadRunner
{
public static void main(String[] args)
{
BankAccount account = new BankAccount();
final double AMOUNT = 100;
final int REPETITIONS = 100;
final int THREADS = 100;
for (int i = 1; i <= THREADS; i++)
{
DepositRunnable d = new DepositRunnable(
account, AMOUNT, REPETITIONS);
WithdrawRunnable w = new WithdrawRunnable(
account, AMOUNT, REPETITIONS);
Thread dt = new Thread(d);
Thread wt = new Thread(w);
dt.start();
wt.start();
}
}
}
DepositRunnable.Java
/**
A deposit runnable makes periodic deposits to a bank account.
*/
public class DepositRunnable implements Runnable
{
private static final int DELAY = 1;
private BankAccount account;
private double amount;
private int count;
/**
Constructs a deposit runnable.
@param anAccount the account into which to deposit money
@param anAmount the amount to deposit in each repetition
@param aCount the number of repetitions
*/
public DepositRunnable(BankAccount anAccount, double
anAmount,
int aCount)
{
account = anAccount;
amount = anAmount;
count = aCount;
}
public void run()
{
try
{
for (int i = 1; i <= count; i++)
{
account.deposit(amount);
Thread.sleep(DELAY);
}
}
catch (InterruptedException exception) {}
}
}
WithdrawRunnable.Java
/**
A withdraw runnable makes periodic withdrawals from a bank
account.
*/
public class WithdrawRunnable implements Runnable
{
private static final int DELAY = 1;
private BankAccount account;
private double amount;
private int count;
/**
Constructs a withdraw runnable.
@param anAccount the account from which to withdraw money
@param anAmount the amount to withdraw in each repetition
@param aCount the number of repetitions
*/
public WithdrawRunnable(BankAccount anAccount, double
anAmount,
int aCount)
{
account = anAccount;
amount = anAmount;
count = aCount;
}
public void run()
{
try
{
for (int i = 1; i <= count; i++)
{
account.withdraw(amount);
Thread.sleep(DELAY);
}
}
catch (InterruptedException exception) {}
}
}
Given question is of bank accounts
and thread program for withdraw and deposit fucntionality
Brief description of solution:
synchronised(this)
it is used to avoid exception IllegalMonitorStateException as it is done if calling thread does not own the specified monitor means current execution so adding synchronization means till this thread is stopped no such same thread is called again like if deposit thread is on wait no such deosit thread is called
for wait, notify and notifyall method, the calling thread must own therefore own the monitor.
concept of wait and notify
wait is used to allow to take a timeout specified by millisecond if not specifed then it will be infinte until it is notified
whereas notify is to wake up thread waiting for a particular object
Solution code:
BankAccount.java {class} {Changed}
//code is well commented for better understanding
/**
A bank account has a balance that can be changed by
deposits and withdrawals.
*/
public class BankAccount
{
private double balance;
/**
Constructs a bank account with a zero balance.
*/
public BankAccount()
{
balance = 0;
}
/**
Deposits money into the bank account.
@param amount the amount to deposit
* @throws InterruptedException
*/
public void deposit(double amount) throws InterruptedException
{
//to check for balance limitation and can not be more than given limit(100000)
//so have to wait for other threads until they withdraw amount
if(balance>=100000)
{
synchronized (this)
{
wait();
}
}
else
{
//no notifying thread so it wake up and does not wait
//if this was not there then deposit would not be done even after withdrawal
synchronized (this)
{
notify();
}
System.out.print("Depositing " + amount);
double newBalance = balance + amount;
System.out.println(", new balance is " + newBalance);
balance = newBalance;
}
}
/**
Withdraws money from the bank account.
@param amount the amount to withdraw
* @throws InterruptedException
*/
public void withdraw(double amount) //throws InterruptedException
{
//to check for balance < 0 although it is not mentioned in question but just for reference
/*if(balance<=0)
{
synchronized (this)
{
wait();
}
}
else
{
//no notifying thread so it wake up and does not wait
synchronized (this)
{
notify();
}*/
System.out.print("Withdrawing " + amount);
double newBalance = balance - amount;
System.out.println(", new balance is " + newBalance);
balance = newBalance;
//}
}
/**
Gets the current balance of the bank account.
@return the current balance
*/
public double getBalance()
{
return balance;
}
}
unchanged class as per question
DepositRunnable.java {class}
/**
A deposit runnable makes periodic deposits to a bank account.
*/
public class DepositRunnable implements Runnable
{
private static final int DELAY = 1;
private BankAccount account;
private double amount;
private int count;
/**
Constructs a deposit runnable.
@param anAccount the account into which to deposit money
@param anAmount the amount to deposit in each repetition
@param aCount the number of repetitions
*/
public DepositRunnable(BankAccount anAccount, double anAmount,
int aCount)
{
account = anAccount;
amount = anAmount;
count = aCount;
}
public void run()
{
try
{
for (int i = 1; i <= count; i++)
{
account.deposit(amount);
Thread.sleep(DELAY);
}
}
catch (InterruptedException exception) {}
}
}
unchanged
WithdrawRunnable.java {class}
/**
A withdraw runnable makes periodic withdrawals from a bank account.
*/
public class WithdrawRunnable implements Runnable
{
private static final int DELAY = 1;
private BankAccount account;
private double amount;
private int count;
/**
Constructs a withdraw runnable.
@param anAccount the account from which to withdraw money
@param anAmount the amount to withdraw in each repetition
@param aCount the number of repetitions
*/
public WithdrawRunnable(BankAccount anAccount, double anAmount,
int aCount)
{
account = anAccount;
amount = anAmount;
count = aCount;
}
public void run()
{
try
{
for (int i = 1; i <= count; i++)
{
account.withdraw(amount);
Thread.sleep(DELAY);
}
}
catch (InterruptedException exception) {}
}
}
unchanged
BankAccountThreadRunner.java {driver class}
/**
This program runs threads that deposit and withdraw
money from the same bank account.
*/
public class BankAccountThreadRunner
{
public static void main(String[] args)
{
BankAccount account = new BankAccount();
final double AMOUNT = 100;
final int REPETITIONS = 100;
final int THREADS = 100;
for (int i = 1; i <= THREADS; i++)
{
DepositRunnable d = new DepositRunnable(
account, AMOUNT, REPETITIONS);
WithdrawRunnable w = new WithdrawRunnable(
account, AMOUNT, REPETITIONS);
Thread dt = new Thread(d);
Thread wt = new Thread(w);
dt.start();
wt.start();
}
}
}
code output as per question only a sample as output is vey big for 100 x 100 repitions
code output for only 2 thread and 10 repition each for withdrawl and deposit and max limit of +100 and amount to deposit/withdaw is also 100
for better verification of code
Note : thread executes randomly so output screenshot with same values may also differ