新闻中心

J*a实现账户转账功能_模拟银行交易逻辑完整流程

2025-12-03
浏览次数:
返回列表
转账功能需保证原子性与并发安全,通过账户排序加锁避免死锁,并结合日志实现事务回滚。

java实现账户转账功能_模拟银行交易逻辑完整流程

账户转账功能是银行系统中最基础也是最核心的业务之一。在J*a中实现这一功能,需要考虑数据一致性、事务管理、异常处理以及并发安全等关键问题。下面通过一个简化的模型,展示如何用J*a模拟银行转账的完整交易逻辑。

1. 账户实体类设计

定义一个Account类,用于表示银行账户,包含账户ID、余额等基本信息,并提供加锁机制防止并发修改。

public class Account {
    private String accountId;
    private double balance;
<pre class='brush:j*a;toolbar:false;'>public Account(String accountId, double balance) {
    this.accountId = accountId;
    this.balance = balance;
}

public synchronized void deposit(double amount) {
    if (amount <= 0) throw new IllegalArgumentException("存款金额必须大于0");
    this.balance += amount;
}

public synchronized boolean withdraw(double amount) {
    if (amount <= 0) throw new IllegalArgumentException("取款金额必须大于0");
    if (balance < amount) return false;
    balance -= amount;
    return true;
}

public String getAccountId() {
    return accountId;
}

public double getBalance() {
    return balance;
}

}

2. 转账服务逻辑实现

转账操作涉及两个账户:转出方和接收方。需确保整个过程具备原子性——要么全部成功,要么全部回滚。

public class TransferService {
<pre class='brush:j*a;toolbar:false;'>public boolean transfer(Account from, Account to, double amount) {
    if (amount <= 0) {
        throw new IllegalArgumentException("转账金额必须大于0");
    }

    // 避免死锁:按账户ID排序锁定
    Account first = from.getAccountId().compareTo(to.getAccountId()) < 0 ? from : to;
    Account second = from == first ? to : from;

    // 双重加锁,保证线程安全
    synchronized (first) {
        synchronized (second) {
            if (!from.withdraw(amount)) {
                return false; // 余额不足
            }
            to.deposit(amount);
            return true;
        }
    }
}

}

这里使用了账户ID排序加锁法来避免死锁。多个线程在转账时,总是先锁定ID较小的账户,再锁较大的,从而保证加锁顺序一致。

3. 异常与事务模拟

真实银行系统中会使用数据库事务(如JDBC或Spring Transaction)。此处用J*a模拟事务行为,记录操作日志并支持失败回滚。

独响 独响

一个轻笔记+角色扮演的app

独响 249 查看详情 独响
public class TransactionLog {
    private List<String> logs = new ArrayList<>();
<pre class='brush:j*a;toolbar:false;'>public void log(String msg) {
    logs.add(LocalDateTime.now() + " - " + msg);
}

public void rollback(Account from, Account to, double amount) {
    to.deposit(amount);   // 撤销到账
    from.withdraw(-amount); // 补回转出金额(注意方向)
    log("事务回滚: " + from.getAccountId() + " → " + to.getAccountId() + ", 金额:" + amount);
}

public void commit(String fromId, String toId, double amount) {
    log(&quot;转账成功: " + fromId + " → " + toId + ", 金额:" + amount);
}

}

TransferService中集成日志和回滚逻辑:

public boolean transferWithLog(Account from, Account to, double amount, TransactionLog log) {
    if (amount <= 0) throw new IllegalArgumentException();
<pre class='brush:j*a;toolbar:false;'>Account first = from.getAccountId().compareTo(to.getAccountId()) < 0 ? from : to;
Account second = from == first ? to : from;

synchronized (first) {
    synchronized (second) {
        boolean success = from.withdraw(amount);
        if (!success) {
            log.log("转账失败:余额不足 - " + from.getAccountId());
            return false;
        }
        to.deposit(amount);

        try {
            // 模拟网络延迟或中间错误
            // 若发生异常应触发回滚(实际中可用try-catch-finally或AOP)
            log.commit(from.getAccountId(), to.getAccountId(), amount);
            return true;
        } catch (Exception e) {
            log.rollback(from, to, amount);
            return false;
        }
    }
}

}

4. 测试用例验证

编写测试代码验证正常转账、余额不足、并发安全等情况。

public class TransferTest {
    public static void main(String[] args) {
        Account accA = new Account("A001", 1000);
        Account accB = new Account("B002", 500);
        TransactionLog log = new TransactionLog();
        TransferService service = new TransferService();
<pre class='brush:j*a;toolbar:false;'>    // 正常转账
    boolean result = service.transferWithLog(accA, accB, 200, log);
    System.out.println("转账结果: " + result);
    System.out.println("A余额: " + accA.getBalance()); // 800
    System.out.println("B余额: " + accB.getBalance()); // 700

    // 余额不足
    result = service.transferWithLog(accA, accB, 900, log);
    System.out.println("二次转账结果: " + result); // false
}

}

基本上就这些。这套实现虽然简化了持久层和分布式事务,但涵盖了银行转账的核心逻辑:账户安全、资金一致性、异常处理与日志追踪。实际项目中可结合Spring Boot + JPA/Hibernate + @Transactional进一步封装。

以上就是J*a实现账户转账功能_模拟银行交易逻辑完整流程的详细内容,更多请关注其它相关文章!


# java实现  # 眉山网站建设推广哪家好  # 这套  # 解决问题  # 中文网  # 回车符  # 相关文章  # 多个  # 全等  # 这一  # 加锁  # 死锁  # java  # 谷歌关键词排名怎么查  # SEO优化客服  # 霍邱定位营销网络推广  # 南昌网站高端建设公司  # 网站建设与网页制作教程  # 句子优化网站图片制作  # 四川seo快速优化  # 驻马店seo网站优化  # 晋中关键词排名费用 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 荒野行动PC版怎么注册_荒野行动PC版账号注册详细流程图文教程  《明末:渊虚之羽》设计师谈设计角色:那会刚毕业 充满激情  在命令行怎么运行html项目_命令行运行html项目方法【教程】  使用Python高效删除Word宏并转换DOCM为DOCX格式  支付宝如何管理隐私设置_支付宝隐私保护的配置技巧  腾讯视频怎么使用多账号家庭管理_腾讯视频家庭多账号统一管理与权限分配教程  葱吃多了会怎样 葱吃多了会伤胃吗  《主播少女的秘密账号迷宫》首支宣传片  抓大鹅无需下载版 抓大鹅秒玩版入口  C++ map遍历方法大全_C++ map迭代器使用总结  Typer应用中动态命令行参数的解析与处理  LocoySpider如何部署到云服务器_LocoySpider云部署的远程配置  解决Flask中Quill编辑器内容提交失败及TypeError的指南  初次安装JDK时环境变量如何正确配置_J*A_HOME与PATH设置规则讲解  C++如何使用AddressSanitizer(ASan)_C++调试工具中检测内存访问错误的利器  蛙漫漫画免费阅读入口_蛙漫官方正版无广告纯净版  qq浏览器打开空白页怎么办 qq浏览器启动后显示白屏的解决教程  圆通快递查询实时追踪 圆通物流包裹状态快速查看  汽车之家官方网站官网入口_汽车之家网页版直接进入  没有大陆身份证/银行卡如何实名微信? 亲测有效的几种方法分享  React Router 嵌套组件中 URL 重定向问题的解决方案  邮政快递单号查询入口 邮政快递物流信息在线查询入口  在Typer应用中优雅地处理和重组任意命令行参数  J*aScript中向JSON对象添加新属性的正确姿势  Animex动漫社网入口地址 Animex动漫社网正版在线入口  Win10桌面图标出现小盾牌怎么办 Win10去除UAC图标教程【解决】  如何更改在 Excel 中打开超链接时的默认浏览器  PHP中高效并行检查多链接状态的教程  解决Tabulator日期时间排序问题的专业指南  Angular Material 垂直步进器:实现底部到顶部排序的教程  漫蛙漫画登录站点 漫蛙2正版漫画快速访问  必由学登录入口 必由学官方网站在线访问链接  Python多线程中正确使用sigwait处理SIGALRM信号  J*aScript中赋值与自增运算符的复杂交互与执行机制  微信网页版扫码登录入口 微信网页版二维码登录入口  J*aScriptWebpack优化_J*aScript构建工具实战  响应式容器内容自动缩放与宽高比维持教程  Pandas DataFrame 多条件优先级排序与排名  优酷会员付费后没到账怎么办_优酷会员充值异常及解决方法  SteamMachine定价或为699美元 大家想入手吗?  iCloud登录入口网页版 苹果iCloud官网登录  Tailwind CSS line-clamp 布局问题解析与修复指南  使用 Pandas 高效处理 .dat 文件:数据清洗与数值计算实战  12306选座系统怎么选连座_12306选座多人连坐操作方法  Python异步编程实践:使用Binance API构建实时交易数据流  TikTok搜索不到用户发布内容怎么办 TikTok用户内容搜索优化方法  照顾宝贝2小游戏点击立即在线玩  深入理解J*a链表中的IPosition接口与使用  精准捕获:如何在页面中监听除特定元素外的所有点击事件  解决Django多数据库/多Schema环境下外键迁移问题 

搜索