Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 1. BankAccountUser
- 2. BankAccount
- 3. SimulationControl
- -----------------------------------------------------------------------------------------------------------------------------------------
- package threads;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- /**
- * A class representing a bank account user.
- * @author tcolburn
- */
- public class BankAccountUser extends Thread {
- /**
- * Creates a new bank account user.
- * @param name the user's name
- * @param account the account used
- * @param transactions an array of integers representing deposits (positive)
- * and withdrawals (negative)
- */
- public BankAccountUser(String name, BankAccount account, int[] transactions) {
- super(name);
- this.waiting = false;
- this.account = account;
- if(transactions == null){
- transactionsRemaining = 0;
- }
- else transactionsRemaining = transactions.length;
- this.transactions = transactions;
- }
- public boolean isWaiting() { return waiting; }
- public void changeWaitingStatus(boolean bool){
- waiting = bool;
- }
- /**
- * Getter for the number of transactions remaining for this user.
- * @return the number of transactions remaining
- */
- public int getTransactionsRemaining() {
- return transactionsRemaining;
- }
- public BankAccount getAccount(){
- return account;
- }
- /**
- * Runs the transactions in a loop.
- * When finished, a message is logged.
- */
- public void run() {
- for (int amount : transactions) {
- if (amount > 0) {
- account.deposit(amount, this);
- }
- else if (amount < 0) {
- try {
- account.withdraw(Math.abs(amount), this);
- } catch (InterruptedException ex) {
- Logger.getLogger(BankAccountUser.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
- else {
- // amount will not be zero
- }
- transactionsRemaining--;
- try {
- Thread.sleep((int)(Math.random() * 100));
- } catch (InterruptedException ex) {
- Logger.getLogger(BankAccountUser.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
- }
- private boolean waiting;
- private final BankAccount account;
- private final int[] transactions;
- private int transactionsRemaining;
- }
- -----------------------------------------------------------------------------------------------------------------------------------------
- package threads;
- /**
- * This class represents a bank account. It provides methods for setting the
- * balance, depositing, and withdrawing.
- * @author tcolburn
- */
- public class BankAccount {
- /**
- * Creates a new bank account.
- * @param logView the viewing area for logging deposit and withdrawal messages
- */
- public BankAccount(LogView logView) {
- this.logView = logView;
- }
- /**
- * Deposits an amount on behalf of a bank account user.
- * A message is logged showing the deposit amount and new balance.
- * Note that an assertion is used to check if this method is thread-safe.
- * @param amount the amount to deposit
- * @param user the user making the deposit
- */
- public synchronized void deposit(int amount, BankAccountUser user) {
- int newBalance = balance + amount;
- logView.log("\n" +user.getName()+ " Depositing $" +amount);
- balance = balance + amount;
- logView.log(". Balance = " + balance);
- checkFinished(user);
- notifyAll();
- assert(balance == newBalance); // should be true if this method is thread-safe
- }
- /**
- * Withdraws an amount on behalf of a bank account user.
- * A message is logged showing the withdrawal amount and new balance.
- * If the withdrawal would cause a negative balance, a runtime exception
- * is thrown.
- * Note that an assertion is used to check if this method is thread-safe.
- * @param amount the amount to withdraw
- * @param user the user making the withdrawal
- * @throws java.lang.InterruptedException
- */
- public synchronized void withdraw(int amount, BankAccountUser user) throws InterruptedException {
- int newBalance = balance - amount;
- logView.log("\n" +user.getName() + " Withdrawing $" + amount);
- while ( amount > balance ) {
- user.changeWaitingStatus(true);
- wait();
- }
- user.changeWaitingStatus(false);
- balance = balance - amount;
- logView.log(". Balance = " + balance);
- checkFinished(user);
- assert(balance == newBalance); // should be true if this method is thread-safe
- }
- /**
- * Private helper method to log user finished message.
- * @param user the bank account user
- */
- private void checkFinished(BankAccountUser user) {
- if (user.getTransactionsRemaining() == 1) {
- logView.log("\n******************************\n " + user.getName() +
- " finished.\n******************************");
- }
- }
- /**
- * Setter to set the initial balance of this bank account.
- * @param balance the initial balance
- */
- public void setBalance(int balance) {
- this.balance = balance;
- }
- /**
- * Getter for the current balance of this bank account.
- * @return the current balance
- */
- public int getBalance() {
- return balance;
- }
- private final LogView logView;
- private int balance;
- }
- ----------------------------------------------------------------------------------------------------------------------------------------
- package threads;
- import java.util.Random;
- import javafx.collections.FXCollections;
- import javafx.geometry.Insets;
- import javafx.geometry.Pos;
- import javafx.scene.control.Button;
- import javafx.scene.control.ComboBox;
- import javafx.scene.control.Control;
- import javafx.scene.control.Label;
- import javafx.scene.layout.HBox;
- import javafx.scene.layout.VBox;
- import javafx.scene.text.Text;
- /**
- * A class providing controls for a bank account simulation.
- * Controls allow for selecting a starting balance for the account,
- * the number of users (siblings) of the account, the transaction limit,
- * the number of transactions each user will make, and a button to
- * run the simulation.
- * @author tcolburn
- */
- public class SimulationControl extends VBox {
- /**
- * Creates the simulation controls arranged in a vertical box
- * @param account the bank account
- * @param logView the message logging area
- */
- public SimulationControl(BankAccount account, LogView logView) {
- this.account = account;
- this.logView = logView;
- balance = new ComboBox(FXCollections.observableArrayList(100, 500, 1000, 10000));
- balance.setValue(100);
- siblings = new ComboBox(FXCollections.observableArrayList(1, 2, 3, 4, 5));
- siblings.setValue(1);
- limit = new ComboBox(FXCollections.observableArrayList(50, 100, 200, 500));
- limit.setValue(50);
- numTransactions = new ComboBox(FXCollections.observableArrayList(10, 25, 50, 100));
- numTransactions.setValue(10);
- setPadding(new Insets(10));
- super.getChildren().addAll(
- new LabeledControl("Starting Balance:", balance),
- new LabeledControl("Number of Siblings:", siblings),
- new LabeledControl("Transaction Limit:", limit),
- new LabeledControl("Transactions per Sibling:", numTransactions),
- new Runner());
- }
- /**
- * A private class for creating labeled combo boxes.
- */
- private class LabeledControl extends HBox {
- public LabeledControl(String label, Control control) {
- setPadding(new Insets(5));
- setSpacing(10);
- setAlignment(Pos.CENTER_LEFT);
- Label lab = new Label(label);
- lab.setPrefWidth(labelWidth);
- super.getChildren().addAll(lab, control);
- }
- }
- /**
- * A private class for the RUN button.
- * When clicked, the users are generated, the account balance is set.
- * and each user's transactions are executed.
- */
- private class Runner extends Button {
- public Runner() {
- super("RUN");
- setOnAction(e -> {
- generateUsers();
- account.setBalance(balance.getValue());
- logView.clear();
- try {
- for (BankAccountUser user : users) {
- user.start();
- }
- parent.start();
- }
- catch(Exception ex) {
- logView.log(ex.getMessage());
- }
- });
- }
- }
- /**
- * A private helper method that generates an array of bank account users
- * as an instance field.
- */
- private void generateUsers() {
- users = new BankAccountUser[siblings.getValue()];
- for (int i = 0; i < users.length; i++) {
- users[i] = new BankAccountUser("Sibling " + (i+1), account, generateTransactions());
- }
- parent = new BankAccountRescuer("Parent", account, null, users);
- }
- /**
- * A private helper method that generates an integer array of random transactions.
- * A positive integer is a deposit; a negative integer is a withdrawal.
- * The transaction amounts are randomly generated within the limit, and whether
- * the amount is a deposit or withdrawal is also random.
- * @return the array of transactions
- */
- private int[] generateTransactions() {
- int[] transactions = new int[numTransactions.getValue()];
- for (int i = 0; i < transactions.length; i++) {
- int amount = GENERATOR.nextInt(limit.getValue()) + 1; // 1 <= amount <= amountLimit
- transactions[i] = GENERATOR.nextBoolean() ? amount : -amount;
- }
- return transactions;
- }
- private static final Random GENERATOR = new Random();
- private final ComboBox<Integer> balance;
- private final ComboBox<Integer> siblings;
- private final ComboBox<Integer> limit;
- private final ComboBox<Integer> numTransactions;
- private final BankAccount account;
- private final LogView logView;
- private BankAccountUser[] users;
- private BankAccountRescuer parent;
- private final double labelWidth = new Text("Transactions per Sibling:").getLayoutBounds().getWidth();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement