I am doing an exercise in Java concurrency. The problem statement is as follows:
Bank holds an array of Accounts. Client do (in a loop) the following operations: (1) work, then sleep for random time (2) check account balance and withdraw random amount if balance>0 (3) work, then sleep for random time (4) deposit random ammout
Multiple clients may access the same account (which I have implemented by choosing random account each time).
Could you please take a look at my code and let me know if something is wrong or is it could be simplified?
Bank class
import java.util.ArrayList;
public class Bank {
private ArrayList<Account> accounts;
public Bank(int accountsCount) {
accounts = new ArrayList<Account>();
for (int i = 0; i < accountsCount; i++) {
accounts.add(new Account(i));
}
}
public Account getRandomAccount() {
return accounts.get((int) (Math.random() * accounts.size()));
}
public void printSummary() {
for (Account a : accounts)
System.out.println(a.toString());
}
}
Account class
public class Account {
private int balance = 1000;
private int number;
public Account(int number) {
this.number = number;
}
public synchronized int getBalance() {
return balance;
}
public synchronized void withdraw(Client client, int bal) {
try {
if (balance >= bal) {
System.out.println(client.getName() + " "
+ "is trying to withdraw from account " + number);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
balance = balance - bal;
System.out.println(client.getName() + " "
+ "has completed withdrawal from account " + number);
} else {
System.out
.println(client.getName()
+ " "
+ "doesn't have enough money for withdraw from account "
+ number);
}
System.out.println(client.getName() + " withdrawal value: "
+ balance + " from account " + number);
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void deposit(Client client, int bal) {
try {
if (bal > 0) {
System.out.println(client.getName() + " "
+ "trying to deposit on account " + number);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
balance = balance + bal;
System.out.println(client.getName() + " "
+ "has completed the deposit on account " + number);
} else {
System.out.println(client.getName() + " "
+ " doesn't have enough money for deposit on account "
+ number);
}
System.out.println(client.getName() + " deposited " + balance
+ " on account " + number);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return "Account " + number + " balance: " + balance;
}
}
Client class
public class Client {
private String name;
public Client(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
Main class
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main extends Thread implements Runnable {
private static final int CLIENT_COUNT = 5;
private static final int CLIENT_ITERATIONS = 5;
private static final int ACCOUNTS_COUNT = 2;
private static final int RAND_MIN = 10;
private static final int RAND_MAX = 10;
private static final int RAND_MIN_AMOUNT = 10;
private static final int RAND_MAX_AMOUNT = 200;
private static Bank bank = new Bank(ACCOUNTS_COUNT);
private Client client;
public Main(Client c) {
client = c;
}
private int randAmount() {
return (new Random()).nextInt((RAND_MAX_AMOUNT - RAND_MIN_AMOUNT) + 1)
+ RAND_MIN_AMOUNT;
}
private int randSleepTime() {
return (new Random()).nextInt((RAND_MAX - RAND_MIN) + 1) + RAND_MIN;
}
public static void main(String[] args) {
for (int i = 0; i < CLIENT_COUNT; i++) {
Main ts1 = new Main(new Client("Person " + i));
ts1.start();
}
}
private void clientWork() {
try {
Thread.sleep(randSleepTime());
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void run() {
for (int i = 0; i < CLIENT_ITERATIONS; i++) {
Account acc = bank.getRandomAccount();
clientWork();
acc.withdraw(client, randAmount());
clientWork();
acc.deposit(client, randAmount());
}
System.out.println("#Account balance: " + Account.getBalance());
}
}
static
variable. Are all the accounts sharing the same balance? Shouldn't there be one balance per account? \$\endgroup\$public static Account account;
inAccount
for? \$\endgroup\$return (Account) accounts.get(...
the cast(Account)
is unnecessary. But my points are merely cosmetic. Functionally your code seems correct, and the style follows best practices. \$\endgroup\$