java多线程场景1-模拟银行账户转账

ops/2024/10/10 22:00:38/

场景:模拟银行账户转账

创建一个模拟银行账户类,支持多线程环境下并发转账操作。确保转账过程中账户余额不会出现负数,并且转账金额正确。

示例代码

银行账户类
有1个属性,账户余额
有3个方法,存款,转账,查账户余额。

java">public class BankAccount {// 账户余额private double balance = 0;private String accountName;public BankAccount(){}public BankAccount(String accountName){this.accountName = accountName;}public BankAccount(String accountName, double balance){this.accountName = accountName;this.balance = balance;}/*** 存款* @param amount 存款金额*/public synchronized void deposit(double amount){if(amount > 0){balance += amount;System.out.printf("账户:%s, 存入金额:%.2f,账户余额:%.2f", accountName, amount, balance);System.out.println();}}/*** 取款* @param amount 取款金额* @return 如果有足够的资金并且取款成功,则返回true;否则返回false;*/public synchronized boolean withdraw(double amount){if(amount > 0 && balance >= amount){balance -= amount;System.out.printf("账户:%s, 取出金额:%.2f,账户余额:%.2f", accountName, amount, balance);System.out.println();return true;}else{System.out.printf("账户:%s, 账户余额不足", accountName);System.out.println();return false;}}/*** 查询账户余额* @return 账户余额*/public synchronized double getBalance(){return this.balance;}
}

转账demo

java">public class BankTransferDemo {public static void transfer(BankAccount from, BankAccount to, double amount) throws InterruptedException {// 模拟网络延迟TimeUnit.MICROSECONDS.sleep((long) (Math.random() * 100));// 取款失败则直接结束if(!from.withdraw(amount)){return;}to.deposit(amount);}public static void main(String[] args) {demo2();}/*** 从不同账户往同一账户存钱*/public static void demo2(){BankAccount account1 = new BankAccount("account1", 1000);BankAccount account2 = new BankAccount("account2", 1000);BankAccount account3 = new BankAccount("account3", 1000);BankAccount account4 = new BankAccount("account4", 1000);BankAccount account5 = new BankAccount("account5", 1000);BankAccount account6 = new BankAccount("account6", 1000);BankAccount account = new BankAccount("account", 0);Thread thread1 = new Thread(() -> {try {transfer(account1, account, 200);} catch (InterruptedException e) {throw new RuntimeException(e);}});Thread thread2 = new Thread(() -> {try {transfer(account2, account, 300);} catch (InterruptedException e) {throw new RuntimeException(e);}});Thread thread3 = new Thread(() -> {try {transfer(account3, account, 400);} catch (InterruptedException e) {throw new RuntimeException(e);}});Thread thread4 = new Thread(() -> {try {transfer(account4, account, 500);} catch (InterruptedException e) {throw new RuntimeException(e);}});Thread thread5 = new Thread(() -> {try {transfer(account5, account, 600);} catch (InterruptedException e) {throw new RuntimeException(e);}});Thread thread6 = new Thread(() -> {try {transfer(account6, account, 1200);} catch (InterruptedException e) {throw new RuntimeException(e);}});thread1.start();thread2.start();thread3.start();thread4.start();thread5.start();thread6.start();try {thread1.join();thread2.join();thread3.join();thread4.join();thread5.join();thread6.join();} catch (InterruptedException e) {throw new RuntimeException(e);}// 输出账户余额System.out.printf("Final Balances: Account1: %.2f", account.getBalance());}/*** 从同一账户多次取钱,存入同一账户*/public static void demo1(){BankAccount account1 = new BankAccount("account1");BankAccount account2 = new BankAccount("account2");// 初始存款account1.deposit(1000);// 创建线程执行转载操作Thread thread1 = new Thread(() -> {try {transfer(account1, account2, 200);} catch (InterruptedException e) {throw new RuntimeException(e);}});// 创建线程执行转载操作Thread thread2 = new Thread(() -> {try {transfer(account1, account2, 100);} catch (InterruptedException e) {throw new RuntimeException(e);}});thread1.start();thread2.start();try {thread1.join();thread2.join();} catch (InterruptedException e) {throw new RuntimeException(e);}// 输出账户余额System.out.printf("Final Balances: Account1: %.2f, Account2: %.2f%n", account1.getBalance(), account2.getBalance());}

demo1的结果
在这里插入图片描述
demo2的结果
在这里插入图片描述

总结

其实模拟的是多个线程无序地访问和修改同一个共享资源。


http://www.ppmy.cn/ops/123666.html

相关文章

Teigha.NET项目创建示例

项目配置 Teigha_Net_4.00_10下载 创建.NET Framework 4.7.2控制台应用项目。将Teigha_Net_4.00_10文件夹复制到项目Debug文件夹内。在项目的App.config文件中配置Teigha_Net_4.00_10文件夹路径(这样就无需把Teigha_Net_4.00_10里面的文件全部复制到Debug文件夹&a…

python交互式命令时如何清除

在交互模式中使用Python,如果要清屏,可以import os,通过os.system()来调用系统命令clear或者cls来实现清屏。 [python] view plain copy print? >>> import os >>> os.system(clear) 但是此时shell中的状态是:…

VUE2常见问题以及解决方案汇总(不断更新中)

解决vue项目中 el-table 的 row-click 事件与行内点击事件冲突,点击事件不生效(表格行点击事件和行内元素点击事件冲突)需要阻止事件冒泡 问题描述 1.点击列的编辑按钮,会触发按钮本身事件,同时会触发行点击事件 2.点…

汽车网关(GW)技术分析

一、引言 在现代汽车电子系统中,汽车网关(Gateway,简称 GW)扮演着至关重要的角色。随着汽车电子技术的不断发展,汽车内部的电子控制单元(Electronic Control Unit,简称 ECU)数量不断…

Redis: 集群测试和集群原理

集群测试 1 ) SET/GET 命令 测试 set 和 get 因为其他命令也基本相似,我们在 101 节点上尝试连接 103 $ /usr/local/redis/bin/redis-cli -c -a 123456 -h 192.168.10.103 -p 6376我们在插入或读取一个 key的时候,会对这个key做一个hash运算&#xff0c…

pnpm设置镜像源

# 查询当前使用的镜像源 pnpm get registry# 设置为淘宝镜像源 pnpm config set registry https://registry.npmmirror.com/# 还原为官方镜像源 pnpm config set registry https://registry.npmjs.org/参考链接 https://blog.csdn.net/weixin_45046532/article/details/139681…

UGUI(三大现成UI控件)

Rawimage 可以是任意类型的图,所以这里的泛型就更宽泛,不止sprite 相比Image唯二的不同 uvrect有点像平铺 Text suddenly come to a Free island. best fit开启后会有范围选择 Image image 组件是挂在RectTransform的ui下的,换句话说&…

安卓上的iso 是哪几个gain 相乘

在安卓的相机系统中,ISO 表示感光度,它实际上反映的是图像传感器对光线的整体响应度。ISO 值的调整可以通过增益(gain)的调节实现,增益会放大传感器采集的信号强度。通常,ISO 是通过以下几种增益相乘得到的…