Такой вывод однажды появился из-за того, что переменная balance (поле в классе BankAccount) не помечена volatile? Методы deposit и withdraw естественно синхронизовал
Добавляем 1000, на счету 1000
Тратим 100, на счету 900
Тратим 100, на счету 800
Тратим 100, на счету 700
Тратим 100, на счету 600
Тратим 100, на счету 500
Тратим 100, на счету 400
Тратим 100, на счету 300
Тратим 100, на счету 200
Тратим 100, на счету 100
Тратим 100, на счету 0
Недостаточно денег
Добавляем 1000, на счету 1000
Недостаточно денег
Недостаточно денег
Тратим 100, на счету 900
Тратим 100, на счету 800
package com.javarush.task.task17.task1720;
public class Bankomat {
static BankAccount account = new BankAccount("Amigo");
public static volatile boolean isStopped;
public static void main(String[] args) throws InterruptedException {
addMoney.start();
SpendThread spendThread = new SpendThread();
SpendThread spendThread1 = new SpendThread();
SpendThread spendThread2 = new SpendThread();
spendThread.start();
spendThread1.start();
spendThread2.start();
Thread.sleep(4000);
isStopped = true;
}
private static Thread addMoney = new Thread() {
@Override
public void run() {
while (!isStopped) {
account.deposit("1000"); //кладем на счет
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
}
};
public static class SpendThread extends Thread {
@Override
public void run() {
while (!isStopped) {
try {
account.withdraw("100"); //снимаем со счета
} catch (NotEnoughMoneyException e) {
System.out.println("Недостаточно денег");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
}
}
}
}
package com.javarush.task.task17.task1720;
import java.math.BigDecimal;
public class BankAccount {
private BigDecimal balance;
private String owner;
public BankAccount(String owner) {
this(BigDecimal.ZERO, owner);
}
public BankAccount(BigDecimal balance, String owner) {
this.balance = balance;
this.owner = owner;
}
public synchronized void deposit(BigDecimal money) {
BigDecimal newBalance = balance.add(money);
System.out.println("Добавляем " + money + ", на счету " + newBalance);
balance = newBalance;
}
public synchronized void withdraw(BigDecimal money) throws NotEnoughMoneyException {
BigDecimal newBalance = balance.subtract(money);
if (newBalance.compareTo(BigDecimal.ZERO) < 0) throw new NotEnoughMoneyException();
balance = newBalance;
System.out.println("Тратим " + money + ", на счету " + balance);
}
public void deposit(String money) {
deposit(new BigDecimal(money));
}
public void withdraw(String money) throws NotEnoughMoneyException {
withdraw(new BigDecimal(money));
}
}