【问题标题】:Simple use for synchronization in JavaJava中同步的简单使用
【发布时间】:2015-12-20 03:34:11
【问题描述】:

嗯,我为使用同步的银行系统编写了一个程序。我遇到了一些错误,输出没有正确计算提款金额,并且整个输出的打印顺序不是线程的顺序……请帮助提出建议。谢谢。

帐户.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 synchronization runnable implements java-threads


【解决方案1】:

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

现在,您将synchronized 关键字放在DepositThreadWithdrawThreadrun 方法上。然后创建多个实例。因此,这些实例中的每一个都是完全独立的,同步关键字仅“锁定”您当前正在运行的特定 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);
    }

}

【讨论】:

  • 嗯,那么同步属于哪里?在哪个班?
  • 我已经在我的答案中添加了代码,应该可以清楚地说明这一点。
  • 好的,所以我使用了您的 Account 类,并调整了类public class WithdrawThread implements Runnable { private Account account; private double amount; public WithdrawThread(Account account, double amount) { // Set the account &amp; balance this.account = account; this.amount = amount; } public void run() { try { account.withdraw(amount); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}//end Wit
猜你喜欢
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 2010-10-12
  • 2023-02-08
  • 2011-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多