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.
Bank account class: (THE ONE THAT NEEDS TO BE EDITED)
/**
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;
}
}
Included for test classes:
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();
}
}
}
Withdraw runnable.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;
}
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) {}
}
}
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.
Bank account class: (THE ONE THAT NEEDS TO BE EDITED)
Explanation:
Given question is of bank accounts
and thread program for withdraw and deposit functionality
Brief description of solution:
synchronized(this)
it is used to avoid exception Illegal Monitor State Exception 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 deposit thread is called
for wait, notify and notify all 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 specified then it will be infinite until it is notified
whereas notify is to wake up thread waiting for a particular object
Solution code:
BankAccount./**
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();
}
}
}
BankAccount.java {class}
//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;
}
}
/**
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;
}
/**
Constructs a bank account with a given balance.
@param initialBalance the initial balance
*/
public BankAccount(double initialBalance)
{
balance = initialBalance;
}
/**
Deposits money into the bank account.
@param amount the amount to deposit
*/
public void deposit(double amount)
{
double newBalance = balance + amount;
balance = newBalance;
}
/**
Withdraws money from the bank account.
@param amount the amount to withdraw
*/
public void withdraw(double amount)
{
int charge = 1;
double newBalance = balance - amount;
balance = newBalance;
// your work here
balance = balance - charge;
}
/**
Gets the current balance of the bank account.
@return the current balance
*/
public double getBalance()
{
return balance;
}
}
unchanged class as per question
DepositRunnable. {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. {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();
}
}
}