The following source code demonstrates a Bank Operations using Threads in Java.
The demo uses Bank, Clerk and Account and Transaction objects to complete the operation. Actually this demo shows how you can use threads to perform the tasks in their own capacity and utilize the maximum system resources. What we do is, we have two clerks and they will do the work separately from each other hence they will work faster using threads. Clerk class implements Runnable interface so that its object will be a thread.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | import java.util.Random; public class BankOperation { public static void main(String[] args) { int[] initialBalance = { 500, 800 }; // The initial account balances. int[] totalCredits = new int[initialBalance.length]; // Total credits. int[] totalDebits = new int[initialBalance.length]; // Total debits. int[] nCredits = new int[initialBalance.length]; // Number of credits. int[] nDebits = new int[initialBalance.length]; // Number of debits. int transactionCount = 20; // Number of debits and of credits. // Create the bank and the clerks: Bank theBank = new Bank(); // Create a bank. Clerk clerk1 = new Clerk(theBank); // Create the first clerk. Clerk clerk2 = new Clerk(theBank); // Create the second clerk. // Create the accounts, and initialize total credits and debits: Account[] accounts = new Account[initialBalance.length]; for (int i = 0; i < initialBalance.length; i++) { accounts[i] = new Account(i + 1, initialBalance[i]); // Create accounts totalCredits[i] = totalDebits[i] = 0; nCredits[i] = nDebits[i] = 0; } // Create the threads for the clerks as daemon, and start them off: Thread clerk1Thread = new Thread(clerk1); Thread clerk2Thread = new Thread(clerk2); clerk1Thread.setDaemon(true); // Set first as daemon. clerk2Thread.setDaemon(true); // Set second as daemon. clerk1Thread.start(); // Start the first. clerk2Thread.start(); // Start the second. // Generate transactions of each type and pass to the clerks: Random rand = new Random(); // Random number generator Transaction transaction; // Stores a transaction int amount; // stores an amount of money int select; // Selects an account for (int i = 1; i <= transactionCount; i++) { // Generate a credit or debit at random: if (rand.nextInt(2) == 1) { // Generate a random account index for credit operation: select = rand.nextInt(accounts.length); amount = 50 + rand.nextInt(26); // Generate amount of $50 to $75 transaction = new Transaction(accounts[select], // Account Transaction.CREDIT, // Credit transaction amount); // of amount totalCredits[select] += amount; // Keep total credit tally nCredits[select]++; clerk1.doTransaction(transaction); } else { // Generate a random account index for debit operation: select = rand.nextInt(accounts.length); amount = 30 + rand.nextInt(31); // Generate amount of $30 to $60. transaction = new Transaction(accounts[select], // Account. Transaction.DEBIT, // Debit transaction of amount. amount); totalDebits[select] += amount; // Keep total debit tally. nDebits[select]++; clerk2.doTransaction(transaction); } } // Wait until both clerks are done: clerk1.isBusy(); clerk2.isBusy(); // Now output the results: for (int i = 0; i < accounts.length; i++) System.out.println("Account Number:" + accounts[i].getAccountNumber() + "\n" + "Number of credits : " + nCredits[i] + "\n" + "Number of debits : " + nDebits[i] + "\n" + "Original balance : $" + initialBalance[i] + "\n" + "Total credits : $" + totalCredits[i] + "\n" + "Total debits : $" + totalDebits[i] + "\n" + "Final balance : $" + accounts[i].getBalance() + "\n" + "Should be : $" + (initialBalance[i] + totalCredits[i] - totalDebits[i]) + "\n" ); } } //*********************** //Bank.java //*********************** class Bank { // Perform a transaction: public void doTransaction(Transaction transaction) { switch (transaction.getTransactionType()) { case Transaction.CREDIT: synchronized(transaction.getAccount()) { System.out.println("Start credit of " + transaction.getAccount() + " amount: " + transaction.getAmount() ); // Get current balance: int balance = transaction.getAccount().getBalance(); // Credits require require a lot of checks: try { Thread.sleep(10); // wait() time reduced to speed things up. } catch (InterruptedException e) { System.out.println(e); } balance += transaction.getAmount(); // Increment the balance. transaction.getAccount().setBalance(balance); // Restore account balance. break; } case Transaction.DEBIT: synchronized(transaction.getAccount()) { System.out.println("Start debit of " + transaction.getAccount() + " amount: " + transaction.getAmount()); // Get current balance int balance = transaction.getAccount().getBalance(); // Debits require even more checks... try { Thread.sleep(15); // wait()time reduced to speed things up. } catch (InterruptedException e) { System.out.println(e); } balance -= transaction.getAmount(); // Increment the balance. transaction.getAccount().setBalance(balance); // Restore account balance. break; } default: // We should never get here. System.out.println("Invalid transaction"); System.exit(1); } } } //**************************** //Account.java //**************************** // Defines a customer account. public class Account { // Constructor: public Account(int accountNumber, int balance) { this.accountNumber = accountNumber; // Set the account number. this.balance = balance; // Set the initial balance. } // Return the current balance: public int getBalance() { return balance; } // Set the current balance: public void setBalance(int balance) { this.balance = balance; } public int getAccountNumber() { return accountNumber; } public String toString() { return "A//C No. " + accountNumber + " : $" + balance; } private int balance; // The current account balance. private int accountNumber; // Identifies this account. } //*************************** //Clerk.java //*************************** import java.util.*; public class Clerk implements Runnable { Bank theBank; // The in-tray holding transactions: private List inTray = Collections.synchronizedList(new LinkedList()); private int maxTransactions = 8; // Maximum transactions in the in-tray. // Constructor public Clerk(Bank theBank) { this.theBank = theBank; // Who the clerk works for. //inTray = null; //Commented out: don't need this now. } // Receive a transaction: synchronized public void doTransaction(Transaction transaction) { while (inTray.size() >= maxTransactions) try { wait(); } catch (InterruptedException e) { System.out.println(e); } inTray.add(transaction); notifyAll(); } // The working clerk: synchronized public void run() { while (true) { while (inTray.size() == 0) // No transaction waiting? try { wait(); // Then take a break until there is. } catch (InterruptedException e) { System.out.println(e); } theBank.doTransaction((Transaction) inTray.remove(0)); notifyAll(); // Notify other threads locked on this clerk. } } // Busy check: synchronized public void isBusy() { while (inTray.size() != 0) // Is this object busy? try { wait(); // Yes, so wait for notify call. } catch (InterruptedException e) { System.out.println(e); } return; // It is free now. } } //**************************** //Transaction.java //**************************** class Transaction { // Transaction types: public static final int DEBIT = 0; public static final int CREDIT = 1; public static String[] types = { "Debit", "Credit" }; // Constructor: public Transaction(Account account, int transactionType, int amount) { this.account = account; this.transactionType = transactionType; this.amount = amount; } public Account getAccount() { return account; } public int getTransactionType() { return transactionType; } public int getAmount() { return amount; } public String toString() { return types[transactionType] + " A//C: " + ": $" + amount; } private Account account; private int amount; private int transactionType; } |