角色介绍:
1)夫妻账户 (Account)
2)夫 - 存款人 (Husband)
3)妻 - 取款人(Wife)
思路:由于账户的操作必须是原子性的,所以一定是同一时刻同一账户只能被一个人操纵(即使是两个人同时操作手机,对于账户来说,也是有顺序的)因此把账户写成了一个唯一的单例模式。而对该账户的所有操作,都必须是上了锁的。因此账户是重点
以下是代码部分:
一、账户
package com.cloud.test;
import lombok.Data;
import java.math.BigDecimal;
/**
* 账户
* @author
* @date 2022/1/25 14:59
*/
@Data
public class Account {
/**
* 账户操作人
*/
private String name;
/**
* 账户余额
* 初始化一个0
*/
private BigDecimal money = new BigDecimal("0");
private static Account account = null;
private Account() { }
/**
* 单例 - 懒汉
* @return
*/
public static Account getInstance(){
if(null == account){
synchronized (Account.class){
if(null == account){
account = new Account();
}
}
}
return account;
}
/**
* 存款
* @param name 存款人
* @param money 存款金额
*/
public synchronized void saveMoney(String name,BigDecimal money){
this.name = name;
this.setMoney(this.money.add(money));
System.out.println(name+"来存钱,存入金额:"+money+",剩余金额:"+this.money);
}
/**
* 取款
* @param name 取款人
* @param money 取款金额
*/
public synchronized void drawMoney(String name,BigDecimal money){
if(this.money.subtract(money).compareTo(BigDecimal.ZERO) >= 0){
this.name = name;
this.setMoney(this.money.subtract(money));
System.out.println(name+"来取钱,取走金额:"+money+",剩余金额:"+this.money);
}else{
System.out.println(name+"来取钱,账户余额不足!");
}
}
public static void main(String[] args) {
//初始化一个男人存款
Husband man = new Husband("N",new BigDecimal("100"));
//初始化一个女人取款
Wife women = new Wife("S",new BigDecimal("100"));
Thread t1 = new Thread(women);
//Thread t2 = new Thread(women);
Thread t3 = new Thread(man);
//Thread t4 = new Thread(man);
t1.start();
//t2.start();
t3.start();
//t4.start();
}
}
二、初始化存款对象
package com.cloud.test;
import lombok.Data;
import java.math.BigDecimal;
/**
* 丈夫 - 负责存款
* @author
* @date 2022/1/25 14:22
*/
@Data
public class Husband implements Runnable{
private String name;
private BigDecimal money;
public Husband(String name, BigDecimal money) {
this.name = name;
this.money = money;
}
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see Thread#run()
*/
@Override
public void run() {
Account account = Account.getInstance();
int i = 0;
while (i<15){
i++;
account.saveMoney(name,money);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
三、初始化取款对象
package com.cloud.test;
import lombok.Data;
import java.math.BigDecimal;
/**
* 妻子 - 负责取款
* @author
* @date 2022/1/25 14:29
*/
@Data
public class Wife implements Runnable{
private String name;
/**
* 取款金额
*/
private BigDecimal drawMoney;
public Wife(String name, BigDecimal drawMoney) {
this.name = name;
this.drawMoney = drawMoney;
}
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see Thread#run()
*/
@Override
public void run() {
Account account = Account.getInstance();
int i = 0;
while(i < 15){
account.drawMoney(name,drawMoney);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
}
执行结果如下图: