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

场景:模拟银行账户转账

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

示例代码

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

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

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的结果
在这里插入图片描述

总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值