题目:
假设创建并启动两个任 务,一个用来向账户中存款,存入一个随机金额,另外一个 从同一账户中提款,提款一个随机金额。当提款的数额大于 账户的当前余额时,提款线程必须等待。
运行结果:
代码:
public class Test {
public static void main(String[] args) {
Account account = new Account(0);// 创建一个用户账户,初始余额为0
DrawThread drawThread = new DrawThread("小王", account);
DepositThread depositThread = new DepositThread("老王", account);
drawThread.start();
depositThread.start();
}
}
//取款线程
class DrawThread extends Thread {
private Account account; //账户对象
public DrawThread(String name, Account account) {
super(name);
this.account = account;
}
@Override
public void run() {
while(true) {
account.withdraw((int)(Math.random() * 100));//随机取款数额
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//存款线程
class DepositThread extends Thread {
private Account account; //账户对象
public DepositThread(String name, Account account) {
super(name);
this.account = account;
}
@Override
public void run() {
while(true){
account.deposit((int)(Math.random() * 100));//随机存款数额
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Account {
private Lock lock = new ReentrantLock();
private Condition conditionDeposit = lock.newCondition(); // Condition存款对象
private Condition conditionWithdraw = lock.newCondition(); // Condition取款对象
private int balance; //账户余额
public Account(int balance) {
this.balance = balance;
}
public void withdraw(int drawAmount) { // 取款方法
try {
lock.lock(); // 上锁
while (balance < drawAmount) //当取款的数额大于账户的当前余额时,取款线程必须等待
{
System.out.println("余额为:"+balance+" 取款为:"+drawAmount+",当前余额不足不能取款,等待新的存款");
conditionWithdraw.await(); //取款处于等待状态
}
balance -= drawAmount;
System.out.println(Thread.currentThread().getName() + "取款成功,取款金额" + drawAmount + ",余额为:"+ balance);
conditionDeposit.signal(); // 唤醒存款线程
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
public void deposit(int depositAmount) { //存款方法
try {
lock.lock(); // 上锁
balance += depositAmount;
System.out.println(Thread.currentThread().getName() + "存款成功,存款金额为:" + depositAmount + ",余额为:"+ balance);
conditionWithdraw.signal(); // 唤醒取款线程
} finally {
lock.unlock(); //释放锁
}
}
}
总结:
ReentrantLock是可重入锁,是Lock的实现类。可重入就是说线程已经获得锁后可以再次获取锁而不会出现死锁。
Condition的await()和signal()方法用来替代传统的Object的wait()、notify()方法
Condition的await()和signal()方法要在lock()和unlock()方法之间使用