嗯,我写了一个使用同步的银行系统程序。我遇到了一些错误,输出无法正确计算提款金额,并且整个输出的打印顺序不符合线程的顺序……请提供帮助。谢谢。

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()
}


有一个输出:
java - 简单用于Java同步-LMLPHP

最佳答案

您误解了synchronized的用法。此关键字在您正在其中运行的实例对象中运行。

现在,您将synchronized关键字放在runDepositThreadWithdrawThread方法上。然后创建多个实例。因此,这些实例中的每个实例都是完全独立的,并且synced关键字仅“锁定”您当前正在运行的特定DepositThread或WithdrawThread。
如此有效,您根本不需要同步。

您还将以非面向对象的方式对此进行建模。您应该将withdrawdeposit方法移到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);
    }

}

09-11 20:03
查看更多