许多在单线程情况下的代码放到多线程环境下容易出现线程安全问题 通过模拟取钱过程演示线程安全问题。 一般取钱过程:
-
用户输入账户、密码,系统判断用户的账户、密码是否匹配。 -
用户输入取款金额。 -
系统判断账户余额是否大于取款金额。 -
如果余额大于取款金额,则取款成功;如果余额小于取款金额,则取款失败。 在模拟过程中就模拟后面三步,没有模拟账户密码验证过程。 代码:public class TakeMoney1Demo { public static void main(String[] args) { Account account=new Account(“张三”, 5000); TakeMoney1 takeMoney1=new TakeMoney1(“A”,account,900); TakeMoney1 takeMoney2=new TakeMoney1(“B”,account,4500); //通过随机数,随机先启动某个线程
Random random=new Random();
int randomInt=random.nextInt(100);
if(randomInt % 2 ==0) {
takeMoney1.start();
takeMoney2.start();
}else {
takeMoney2.start();
takeMoney1.start();
}
//等待子线程结束
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(account.getNumber() + "账户最终余额: " + account.getMoney());
} }
class TakeMoney1 extends Thread{ //谁取钱 private String name; //账户 private Account account; //取多少钱 private double takeMoney; /** * 构造器 * @param name取钱人 * @param account账户 * @param takeMoney取多少钱 */ public TakeMoney1(String name, Account account, double takeMoney) { super(); this.name = name; this.account = account; this.takeMoney = takeMoney; }
@Override
public void run() {
if(takeMoney<=account.getMoney()) {
//模拟取钱成功
System.out.println(this.name + "取钱成功,取出 " + takeMoney + "元");
//线程暂停 10ms 模拟网络传输
try {
sleep(10);
}catch (InterruptedException e) {
e.printStackTrace();
}
//修改余额
double money=account.getMoney()-takeMoney;
System.out.println(this.name + "取钱后,计算余额= " + money);
account.setMoney(money);
System.out.println(this.name + "取钱后,账户: " + account.getNumber()
+"金额为: "+account.getMoney());
}else {
System.out.println(this.name + "取钱失败,原因: " + account.getNumber() + "账户余额不足");
}
}
}
|