在Java中,线程通信是一个非常重要的概念,特别是在多线程环境下进行资源共享和管理时。为了模拟一个ATM取款的场景,我们可以利用Java中的wait()
和notify()
机制来实现线程间的通信。以下是对这一机制的详细介绍以及相应的代码示例。
场景描述
假设我们有一个ATM机,用户可以通过这个ATM机进行取款,但ATM机的现金是有限的。在我们的例子中,可能会有多个用户试图同时从ATM机中取款,而ATM机则需要按照一定的规则进行处理。如果ATM机中的现金不足以满足某个用户的取款请求,该请求需要被挂起,直到ATM机中补充了足够的现金。
线程通信机制
在Java中,wait()
和notify()
是用于处理线程间通信的两种方法。具体来说:
wait()
:当一个线程调用这个方法后,它会释放当前对象的锁,并进入等待状态,直到其他线程调用与之相对应的notify()
或notifyAll()
方法。notify()
:当一个线程调用这个方法时,会随机唤醒一个在该对象上等待的线程。被唤醒的线程需要重新获得锁才能继续执行。
实现代码示例
以下是一个模拟ATM取款的简单例子,其中包含多个线程试图从ATM机中取款,使用wait()
和notify()
机制来处理情况。
class ATM {
private int cash = 1000; // ATM机初始现金
private final Object lock = new Object(); // 锁对象
// 取款方法
public void withdraw(int amount) throws InterruptedException {
synchronized (lock) {
// 如果当前现金不足,等待补款
while (amount > cash) {
System.out.println(Thread.currentThread().getName() + " 取款失败,ATM机现金不足,当前现金为:" + cash);
lock.wait(); // 释放锁并等待
}
// 如果足够,进行取款
cash -= amount;
System.out.println(Thread.currentThread().getName() + " 成功取款:" + amount + ",当前现金为:" + cash);
}
}
// 补款方法
public void deposit(int amount) {
synchronized (lock) {
cash += amount;
System.out.println("ATM机补款:" + amount + ",当前现金为:" + cash);
lock.notifyAll(); // 唤醒等待的线程
}
}
}
class WithdrawThread extends Thread {
private ATM atm;
private int amount;
public WithdrawThread(ATM atm, int amount) {
this.atm = atm;
this.amount = amount;
}
@Override
public void run() {
try {
atm.withdraw(amount);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class DepositThread extends Thread {
private ATM atm;
private int amount;
public DepositThread(ATM atm, int amount) {
this.atm = atm;
this.amount = amount;
}
@Override
public void run() {
atm.deposit(amount);
}
}
public class ATMTest {
public static void main(String[] args) {
ATM atm = new ATM();
// 创建取款线程
Thread withdraw1 = new WithdrawThread(atm, 700);
Thread withdraw2 = new WithdrawThread(atm, 400);
Thread withdraw3 = new WithdrawThread(atm, 200);
// 创建补款线程
Thread deposit = new DepositThread(atm, 500);
withdraw1.start();
withdraw2.start();
withdraw3.start();
// 等待一段时间后执行补款
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
deposit.start();
}
}
总结
通过上面的示例,我们成功地实现了一个简单的ATM取款系统。在这个系统中,多个线程尝试取款,而当现金不足时,它们会被挂起,直到有线程补款并唤醒等待的线程。这展示了wait()
和notify()
方法在多线程环境下的应用,为线程间的通信提供了有效的解决方案。