import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
This program is a part of the companion code for Core Java 8th ed.
(http://horstmann.com/corejava)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/**
* This program shows how multiple threads can safely access a data structure.
*
* @version 1.30 2004-08-01
* @author Cay Horstmann
*/
public class SynchBankTest {
public static void main(String[] args) {
Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE);
int i;
for (i = 0; i < NACCOUNTS; i++) {
TransferRunnable r = new TransferRunnable(b, i, INITIAL_BALANCE);
Thread t = new Thread(r);
t.start();
}
}
public static final int NACCOUNTS = 100;
public static final double INITIAL_BALANCE = 1000;
}
/*
* This program is a part of the companion code for Core Java 8th ed.
* (http://horstmann.com/corejava)
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see .
*/
/**
* A runnable that transfers money from an account to other accounts in a bank.
*
* @version 1.30 2004-08-01
* @author Cay Horstmann
*/
class TransferRunnable implements Runnable {
/**
* Constructs a transfer runnable.
*
* @param b
* the bank between whose account money is transferred
* @param from
* the account to transfer money from
* @param max
* the maximum amount of money in each transfer
*/
public TransferRunnable(Bank b, int from, double max) {
bank = b;
fromAccount = from;
maxAmount = max;
}
public void run() {
try {
while (true) {
int toAccount = (int) (bank.size() * Math.random());
double amount = maxAmount * Math.random();
bank.transfer(fromAccount, toAccount, amount);
Thread.sleep((int) (DELAY * Math.random()));
}
} catch (InterruptedException e) {
}
}
private Bank bank;
private int fromAccount;
private double maxAmount;
private int DELAY = 10;
}
/*
* This program is a part of the companion code for Core Java 8th ed.
* (http://horstmann.com/corejava)
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see .
*/
/**
* A bank with a number of bank accounts that uses locks for serializing access.
*
* @version 1.30 2004-08-01
* @author Cay Horstmann
*/
class Bank {
/**
* Constructs the bank.
*
* @param n
* the number of accounts
* @param initialBalance
* the initial balance for each account
*/
public Bank(int n, double initialBalance) {
accounts = new double[n];
for (int i = 0; i < accounts.length; i++)
accounts[i] = initialBalance;
bankLock = new ReentrantLock();
sufficientFunds = bankLock.newCondition();
}
/**
* Transfers money from one account to another.
*
* @param from
* the account to transfer from
* @param to
* the account to transfer to
* @param amount
* the amount to transfer
*/
public void transfer(int from, int to, double amount) throws InterruptedException {
bankLock.lock();
try {
while (accounts[from] < amount)
sufficientFunds.await();
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
sufficientFunds.signalAll();
} finally {
bankLock.unlock();
}
}
/**
* Gets the sum of all account balances.
*
* @return the total balance
*/
public double getTotalBalance() {
bankLock.lock();
try {
double sum = 0;
for (double a : accounts)
sum += a;
return sum;
} finally {
bankLock.unlock();
}
}
/**
* Gets the number of accounts in the bank.
*
* @return the number of accounts
*/
public int size() {
return accounts.length;
}
private final double[] accounts;
private Lock bankLock;
private Condition sufficientFunds;
}