Page 252 - 6253
P. 252
У коді, що імітує роботу банку визначено клас Bank та описано метод transfer().
Даний метод переміщує деяку суму грошей з одного рахунку на інший. Нижче
наведено можливий вихідний код методу transfer() з класу Bank.
public void transfer(int from, int to, double amount) {
System.out.println(Thread.currentThread());
accounts[from] = accounts[from] - amount;
System.out.printf("%10.2f з %d до %d", amount, from, to);
accounts[to] = accounts[to]+amount;
System.out.printf("Загальний баланс:%10.2f%n",
getTotalBalance());
}
Нижче наведено вихідний код класу TransferRunnable. Його метод run() виконує
перевід грошей з фіксованого банківського рахунку. Для кожної транзакції метод
run() вибирає випадковий рахунок і довільну суму, викликає метод transfer() для
об’єкта Bank, а потім переводить потік в стан очікування.
class TransferRunnable implements Runnable {
public void run() {
try {
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) { }
}
}
Під час виконання даної програми, невідомо, яка саме сума знаходиться на
будь-якому банківському рахунку в довільний момент часу. Але в той же час
відомо, що загальна сума грошей за всіма рахунками повинна залишатися
незмінною, оскільки гроші тільки переводяться з одного рахунку на інший, але не
знімаються остаточно. Наприкінці кожної транзакції метод transfer() заново
обчислює кінцеву суму на рахунках і виводить її. При цьому програма працює у
вічному циклі.
Запустивши програму на виконання, можна виявити, що через деякий час
загальний баланс все-таки зміниться. Це пов’язано з тим, що два потоки
намагаються одночасно оновити один і той же рахунок. Припустимо, що два потоки
251