1

我创建了 3 个类,

  1. 类 InCharge - 应检查当前余额,同时检查Client线程应wait()直到InCharge线程完成测试(15 秒)
  2. 类客户端 - 应该每 5 秒取款,但是当InCharge线程运行Client线程应该等到InCharge线程说Notify()
  3. 类银行 - 持有当前余额,并锁定Synchronized块。

根据我的调试,它似乎是InCharge发送Notify()但由于某种原因客户端没有收到通知,我猜问题是因为while(true),但我想不出解决它的方法。

你能帮忙找出问题吗?

主要的:

    public class Main {
    public static void main(String[] args) {
        Object obj = new Object();
        Bank bank = new Bank(100000);

        Client client1 = new Client(obj, bank);
        InCharge inCharge = new InCharge(obj, bank);

        client1.setName("client1");
        inCharge.setName("inCharge");

        client1.start();
        inCharge.start();
    }
}

银行:

public class Bank {
    private int balance;
    private boolean bankIsClose = false;
    public Bank(int balance) {
        this.balance = balance;
    }
    public int getBalance() {
        return balance;
    }

    public boolean isBankIsClose() {
        return bankIsClose;
    }

    public void setBankIsClose(boolean bankIsClose) {
        this.bankIsClose = bankIsClose;
    }

    public void setBalance(int balance) {
        this.balance = balance;
    }
    public synchronized void withdraw(String name, int amount){
        if (this.balance - amount >= 0) {
            this.balance = this.balance - amount;
            System.out.println(name+" "+this.balance + " withdrawed - " + amount);
        }
    }
}

客户:

public class Client extends Thread {
    private Object obj;
    private Bank bank;

    Client(Object obj, Bank bank) {
        this.obj = obj;
        this.bank = bank;
    }

    @Override
    public void run() {
        int randomNumber;
        while (bank.getBalance() > 0) {
            synchronized (obj) {
                randomNumber = ((int) (Math.random() * (5000 - 1000 + 1)) + 1000);
                if (!bank.isBankIsClose()) {
                    try {
                        obj.wait();
                        bank.withdraw(currentThread().getName(), randomNumber);
                    } catch (Exception e) {}
                }
            }
        }
    }
}

负责:

public class InCharge extends Thread {
    private Object obj;
    private Bank bank;

    InCharge(Object obj, Bank bank) {
        this.obj = obj;
        this.bank = bank;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                bank.setBankIsClose(true);
                try {
                    System.out.println("Charge is here!, current balance is: " + bank.getBalance());
                    Thread.sleep(5000);
                } catch (InterruptedException e) {}
                bank.setBankIsClose(false);
                obj.notify();
            }
        }
    }
}
4

1 回答 1

1

你的应用程序确实为我运行而无需更改,但由于银行开/闭环的性质,银行不是很友好。

银行关闭 5 秒,然后打开,但会立即尝试再次进入同步块以关闭银行。有时 InCharge/bank 线程会击败客户端线程来访问synchronized(obj). 这是正常的,也是意料之中的,但这意味着在许多周期中,银行会继续休眠(5000),与前一个周期显示的余额相同,并且在这之间没有客户提款代码运行。

为了模拟银行的正常工作时间,您可以在 InCharge 线程中同步后添加第二个小 sleep(),此期间将显示客户端更频繁地获取锁以进行提款。将 InCharge.run() 更改为:

public void run() {
    while (true) {
        synchronized (obj) {
            bank.setBankIsClose(true);
            try {
                System.out.println("Charge is here!, current balance is: " + bank.getBalance());
                Thread.sleep(5000);
            } catch (InterruptedException e) {}
            bank.setBankIsClose(false);
            System.out.println("Now the bank is open for business");
            obj.notify();
        }

        // Simulate a period of bank being open:
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {}
    }
}

如果您进一步开发应用程序,您应该尝试 2 个客户端线程,并且需要进行更改notify()notifyAll()确保所有客户端都有机会使用银行。还将您的代码更改为 Runnable 而不是扩展 Thread 将使代码更清晰。

于 2020-07-02T17:17:34.683 回答