嗯,我写了一个使用同步的银行系统程序。我遇到了一些错误,输出无法正确计算提款金额,并且整个输出的打印顺序不符合线程的顺序……请提供帮助。谢谢。
Account.java
public class Account {
private double balance = 0;
public Account(double balance) {
this.balance = balance;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
DepositThread.java
public class DepositThread implements Runnable {
private Account account;
private double amount;
public DepositThread(Account account, double amount) {
// Set the account & balance
this.account = account;
this.amount = amount;
}
public void deposit(double amount) throws InterruptedException {
double bal = account.getBalance();
if (amount <= 0) {
wait();
throw new IllegalArgumentException("Can't not deposit!");
}
bal += amount;
account.setBalance(bal);
System.out.println("Deposit " + amount + " new balance in thread number " + Thread.currentThread().getId()
+ " balance is " + bal);
}
public synchronized void run() {
// make a deposit
try {
deposit(amount);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
WithdrawThread.java
public class WithdrawThread implements Runnable {
private Account account;
private double amount;
public WithdrawThread(Account account, double amount) {
// Set the account & balance
this.account = account;
this.amount = amount;
}
public void withdraw(double amount) throws InterruptedException {
double bal = account.getBalance();
if (amount > bal) {
wait();
throw new IllegalArgumentException("Wrong amount!");
}
bal -= amount;
account.setBalance(bal);
notifyAll();
System.out.println("Withdraw " + amount + " new balance in thread number " + Thread.currentThread().getId()
+ " balance is " + bal);
}
public synchronized void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// make a withdrawal
try {
withdraw(amount);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}// end WithdrawThread class
InternetBankingSystem.java
public class InternetBankingSystem {
public static void main(String[] args) {
Account accountObject = new Account(100);
new Thread(new DepositThread(accountObject, 30)).start();
new Thread(new DepositThread(accountObject, 20)).start();
new Thread(new DepositThread(accountObject, 10)).start();
new Thread(new WithdrawThread(accountObject, 30)).start();
new Thread(new WithdrawThread(accountObject, 50)).start();
new Thread(new WithdrawThread(accountObject, 20)).start();
} // end main()
}
有一个输出:
最佳答案
您误解了synchronized
的用法。此关键字在您正在其中运行的实例对象中运行。
现在,您将synchronized
关键字放在run
和DepositThread
的WithdrawThread
方法上。然后创建多个实例。因此,这些实例中的每个实例都是完全独立的,并且synced关键字仅“锁定”您当前正在运行的特定DepositThread或WithdrawThread。
如此有效,您根本不需要同步。
您还将以非面向对象的方式对此进行建模。您应该将withdraw
和deposit
方法移到Account
类中,并使这些方法成为synchronized
。
您可以在Account
类中执行以下操作:
(请注意,您的等待/通知用法没有任何意义。我把它们留在了那里,但是为什么余额不足零时您不能存入资金,即使那是业务规则,您为什么还要然后等待withdraw方法发出通知?因为withdraw方法永远不会使余额超过已经存在的余额)
public class Account {
private double balance = 0;
public Account(double balance) {
this.balance = balance;
}
public double getBalance() {
return balance;
}
public synchronized void deposit(double amount) throws InterruptedException {
double bal = getBalance();
if (amount <= 0) {
wait();
throw new IllegalArgumentException("Can't not deposit!");
}
bal += amount;
this.balance = bal;
System.out.println("Deposit " + amount + " new balance in thread number " + Thread.currentThread().getId()
+ " balance is " + bal);
}
public synchronized void withdraw(double amount) throws InterruptedException {
double bal = getBalance();
if (amount > bal) {
wait();
throw new IllegalArgumentException("Wrong amount!");
}
bal -= amount;
this.balance = bal;
notifyAll();
System.out.println("Withdraw " + amount + " new balance in thread number " + Thread.currentThread().getId()
+ " balance is " + bal);
}
}