Load the BankAccount.java file. The class simulates what happens with a bank account when different processes may be making deposits and withdraws, and it is critical that no money is lost. The basic methods deposit and withdraw add and remove funds. The methods doDeposits and doWithdraws run a lot of random deposits and withdraws. When the methods are done, they set the flags doneDeposits and doneWithdraws to indicate that the simulation is complete. The method checkBalance verifies that the balance amount equals the initial balance plus the sum of all deposits and minus the sum of all withdraws.
Currently the main method does all deposits first and then all withdraws. As a result, there is no chance the balance will be an unexpected value. However, this is unrealistic because in a bank, there will be many processes making withdraws and many processes making deposits. You will simulate this by having separate threads do the depositing and withdrawing.
To launch a thread, you should use the Thread class. The two critical methods of the Thread class are run and start. The run method contains the code that the thread will execute. This method initially does nothing so you need to override it. The start method launches the thread and calls its run method.
Change the main method for the BankAccount class so that it creates three threads. One thread will run the doDeposits method, one thread will run the doWithdraws method, and one thread will wait until both the deposits and withdraws complete (both doneDeposits and doneWithdraws are true) and then calls checkBalance to verify that the account balance is what it should be.
Here is the code to create a Thread that runs the doDeposits method of BankAccount
final BankAccount account = new BankAccount();
Thread t1 = new Thread() { // create a thread that runs doDeposits
public void run() {
account.doDeposits(this);
}
};
t1.start(); // launch the thread
In the code, we are creating an anonymous inner class that extends Thread. The class is called anonymous because we do not give a name for the class. Anonymous classes are useful anytime we need to create a single instance of a class that extends another class or implements an interface.
The variable account is final because Java will not let the inner class use a variable declared outside the class unless we assure it that the value of the variable will not be changing.
To have the third thread wait until the flags are both true, use a while loop that loops as long as either flag is false. You should add the modifier volatile to both flags. This modifier tells the compiler that this field may be modified by another thread. Otherwise the compiler might optimize the loop by not re-examining the values of the flags.
Now try running the program. The first indication that it is working is that the DrJava prompt should return immediately, and then the printed message should appear a second or two later. There should be problems with the final balance.
It is very inefficient to have the third thread use a while loop alone to wait for the other threads to complete. The while loop will continuously execute and so this thread will waste a lot of CPU cycles. Instead, inside the while loop, have the thread sleep for half a second before it tests the loop condition again. You should use the sleep method of Thread. The parameter of the sleep method is the length of time to sleep in milliseconds. The sleep method will throw a InterrupedException. This exception is thrown if something wakes up the thread before the specified sleep time has expired. You need to catch this exception, but it should still stay within the while loop until both flags are set.
Test your code to see that it still works.
The reason that the balance is wrong is that two of the threads are trying to modify it at the same time, and one thread will not complete its modification before another thread changes it. You will prevent this from happening by placing a synchronized modifier on both the withdraw and deposit methods. These are the only two methods that should have the modifier. No other method modifies the balance. (Note that the third thread accesses the flags set by the first two, but this action does not not need to be synchronized because the third thread only reads the contents of the flag, only one thread actually modifies it.)
Test your code and verify that the balance is now correct.