创建账户类
public class Account {
private String accountNum;
private String pwd;
private BigDecimal balance;
public Account(){}
public Account(String accountNum, String pwd, BigDecimal balance) {
this.accountNum = accountNum;
this.pwd = pwd;
this.balance = balance;
}
public String getAccountNum() {
return accountNum;
}
public void setAccountNum(String accountNum) {
this.accountNum = accountNum;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public BigDecimal getBalance() {
return balance;
}
public void setBalance(BigDecimal balance) {
this.balance = balance;
}
}
取钱线程
public class WithdrawTest {
public static void main(String[] args) throws InterruptedException {
Account account = new Account("123456","123456", new BigDecimal(3000));
new WithdrawThread("A线程", account, new BigDecimal(800)).start();
new WithdrawThread("B线程", account, new BigDecimal(800)).start();
}
}
class WithdrawThread extends Thread{
private Account account;
private BigDecimal withdrawAmount;
public WithdrawThread(String name, Account account, BigDecimal withdrawAmount){
super(name);
this.account = account;
this.withdrawAmount = withdrawAmount;
}
@Override
public void run(){
if (account.getAccountNum().equals("123456") && account.getPwd().equals("123456")){
// 判断账户余额大于等于取钱金额
if (account.getBalance().compareTo(withdrawAmount) >=0){
// 减去取的钱数
account.setBalance(account.getBalance().subtract(withdrawAmount));
System.out.println(getName() + "取钱成功,取出金额为:" + withdrawAmount);
System.out.println("余额为:" + account.getBalance());
return;
}
System.out.println(getName() + "取钱失败,余额为:" + account.getBalance());
return;
}
System.out.println("账号或密码不正确");
}
}
这样的线程会出现问题,两条线程交替运行,都可以取钱成功,但这样显然是不可以的。
所以就需要对线程进行操作,让它可以正确的运行。
线程锁
关键词:synchronized
synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
- 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
- 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
- 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
- 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
方法一:同步代码块
@Override
public void run(){
// 使用account作为同步监视器,任何线程进入下面同步代码块之前必须先获取对account的锁定,是的其他线程无法获取锁
// 加锁 -> 处理业务逻辑(修改) -> 释放锁
synchronized (account){
if (account.getAccountNum().equals("123456") && account.getPwd().equals("123456")){
// 判断账户余额大于等于取钱金额
if (account.getBalance().compareTo(withdrawAmount) >=0){
// 减去
account.setBalance(account.getBalance().subtract(withdrawAmount));
System.out.println(getName() + "取钱成功,取出金额为:" + withdrawAmount);
System.out.println("余额为:" + account.getBalance());
return;
}
System.out.println(getName() + "取钱失败,余额为:" + account.getBalance());
return;
}
System.out.println("账号或密码不正确");
}
}
方法二:同步方法
public void run(){
withdraw(withdrawAmount);
}
public synchronized void withdraw(BigDecimal withdrawAmount){
if (account.getAccountNum().equals("123456") && account.getPwd().equals("123456")){
if (account.getBalance().compareTo(withdrawAmount) >=0){
account.setBalance(account.getBalance().subtract(withdrawAmount));
System.out.println(getName() + "取钱成功,取出金额为:" + withdrawAmount);
System.out.println("余额为:" + account.getBalance());
return;
}
System.out.println(getName() + "取钱失败,余额为:" + account.getBalance());
return;
}
System.out.println("账号或密码不正确");
}
方法三:同步锁lock
public void run(){
lock.lock();
try {
if (account.getAccountNum().equals("123456") && account.getPwd().equals("123456")){
if (account.getBalance().compareTo(withdrawAmount) >=0){
account.setBalance(account.getBalance().subtract(withdrawAmount));
System.out.println(getName() + "取钱成功,取出金额为:" + withdrawAmount);
System.out.println("余额为:" + account.getBalance());
return;
}
System.out.println(getName() + "取钱失败,余额为:" + account.getBalance());
return;
}
System.out.println("账号或密码不正确");
}finally {
lock.unlock();
}
}