Java实现多线程操作多账户

前言

某公司一个面试题:

1.有二十个账户,每个账户初始余额10000元。

2.有十个转账线程,对二十个账户中的两个随机选取账户进行转账,转账额度100以内正整数随机数。

3.每个线程执行100次转账操作。

4.最后请打印出二十个账户的余额。

正好很久没有做这类型题了,拿来练练手,结果碰到了一些问题。

正文

方案一:

首先描述下思路,首先用一个List数组存20个账户,然后对每个账户赋初值10000,在新建10个转账线程,对List数组中20个账户进行并发操作,每个线程分别获取两个账户进行随机额度转账。那么最简单的方式就是对List数组进行加锁就可以了。代码实现如下:

public class test {
    static int num;
    public static void main(String[] args) {
        List<Integer> accountList = new ArrayList<Integer>();
        for (int i = 0;i < 20;i++){
            accountList.add(10000);
        }
        System.out.println(num);

        MulThreadTest mulThreadTest = new MulThreadTest(accountList);
        ThreadGroup threadGroup =new ThreadGroup("ThreadGroup1");
        for (int i = 0;i < 10;i++){
            Thread thread = new Thread(mulThreadTest);
            thread.setName("thread="+i);
            thread.start();
        }
        try{
            Thread.sleep(5000);
        }catch(Exception e){
            e.printStackTrace();
        }
        int sum = 0;
        for (int i = 0;i < 20;i++){
            sum = sum + accountList.get(i);
            System.out.println(accountList.get(i));
        }
        System.out.println(sum);
    }
}
public class MulThreadTest implements Runnable{
    private List<Integer> accountList;
    private  int first;
    private  int second;
    private  int num;

    public MulThreadTest(List accountList){
        this.accountList = accountList;
    }
    @Override
    public void run() {
        synchronized (accountList){
            for(int i = 0;i < 100;i ++) {
                first = new Random().nextInt(20);
                second = new Random().nextInt(20);
                if(first == second){
                    if(second < 19){
                        second += 1;
                    }else {
                        second = 1;
                    }

                }
                num = new Random().nextInt(100);
                if(accountList.get(first) - num < 0){
                    i --;
                    continue;
                }
                System.out.println(Thread.currentThread().getName()+",操作前:"+"账户:"+first+"="+accountList.get(first)+"账户:"+second+"="+accountList.get(second));
                accountList.set(first,accountList.get(first) -  num);
                accountList.set(second,accountList.get(second) +  num);
                System.out.println(Thread.currentThread().getName()+",操作:"+"账户:"+first+"="+accountList.get(first)+"=>"+num+"=>"+"账户:"+second+"="+accountList.get(second));
            }
        }

    }
}

以下是20个账户的金额以及总金额

10114
10046
10268
10676
10250
10344
9899
10120
9629
10145
9211
9761
9903
10187
9374
10508
10046
10005
9529
9985
200000

以上可以解决这个转账并发问题,但是锁的粒度还是有点大了,在一个线程操作List时其它线程是没法操作的,那么如何减小锁的粒度,实现更高的效率呢?

方案二:

在方案一的基础上,把锁的对象修改为List中的某个账户,这样当其中一个线程在操作某个账户时,其它线程就仅仅无法操作该账户,影响范围能减小很多。代码实现如下:

public class test {
    static int num;
    public static void main(String[] args) {
        List<Account> accountList = new ArrayList<Account>();
        for (int i = 0;i < 20;i++){
            accountList.add(new Account(10000));
        }
        System.out.println(num);

        MulThreadTest1 mulThreadTest = new MulThreadTest1(accountList);
        ThreadGroup threadGroup =new ThreadGroup("ThreadGroup1");
        for (int i = 0;i < 10;i++){
            Thread thread = new Thread(mulThreadTest);
            thread.setName("thread="+i);
            thread.start();
        }
        try{
            Thread.sleep(5000);
        }catch(Exception e){
            e.printStackTrace();
        }
        int sum = 0;
        for (int i = 0;i < 20;i++){
            sum = sum + accountList.get(i).getNum();
            System.out.println(accountList.get(i).getNum());
        }
        System.out.println(sum);
    }
}
public class MulThreadTest1 implements Runnable{
    private List<Account> accountList;
    Account firstInteger;
    Account secondInteger;


    public MulThreadTest1(List accountList){
        this.accountList = accountList;
    }
    @Override
    public void run() {
         int first;
         int second;
         int num;
         
            for(int i = 0;i < 100;i ++) {
                first = new Random().nextInt(20);
                second = new Random().nextInt(20);
                if(first == second){
                    if(second < 19){
                        second += 1;
                    }else {
                        second = 1;
                    }

                }
                firstInteger = accountList.get(first);

                    synchronized (firstInteger) {

                        num = new Random().nextInt(100);
                        if (firstInteger.getNum() - num < 0) {
                            i--;
                            continue;
                        }
                        System.out.println(Thread.currentThread().getName() + ",操作前:" + "账户:" + first + "=" + accountList.get(first).getNum() + "账户:" + second + "=" + accountList.get(second).getNum());

                        firstInteger.setNum(firstInteger.getNum() - num);

                        accountList.set(first, firstInteger);

                    secondInteger = accountList.get(second);

                        synchronized (secondInteger) {
                            secondInteger.setNum(secondInteger.getNum() + num);
                            accountList.set(second, secondInteger);
                            //accountList.set(first,accountList.get(first) -  num);
                            //accountList.set(second,accountList.get(second) +  num);
                            System.out.println(Thread.currentThread().getName() + ",操作:" + "账户:" + first + "=" + accountList.get(first).getNum() + "=>" + num + "=>" + "账户:" + second + "=" + accountList.get(second).getNum());
                        }
                
                }

                   

            }

    }
}

部分结果如下:

thread=4,操作前:账户:15=10037账户:16=10307
thread=4,操作:账户:15=9972=>65=>账户:16=10372
thread=4,操作前:账户:10=10012账户:16=10372
thread=4,操作:账户:10=9958=>54=>账户:16=10426
thread=4,操作前:账户:3=9854账户:19=9845
thread=6,操作前:账户:14=9842账户:19=9998
thread=0,操作前:账户:19=9845账户:14=9842
thread=5,操作前:账户:2=9821账户:17=10387
thread=5,操作:账户:2=9786=>35=>账户:17=10422
thread=5,操作前:账户:0=9574账户:14=9822
thread=8,操作前:账户:15=9972账户:16=10426
thread=8,操作:账户:15=9962=>10=>账户:16=10436
thread=7,操作前:账户:18=10367账户:19=9760
thread=8,操作前:账户:17=10422账户:10=9958
thread=8,操作:账户:17=10414=>8=>账户:10=9966
thread=8,操作前:账户:1=10552账户:10=9966
thread=8,操作:账户:1=10487=>65=>账户:10=10031
9528
10487
9786
9763
10109
9916
9162
9803
10237
10276
10031
10163
9987
9686
9822
9962
10436
10414
10359
9760
199687

使用jps和jstack即可看到线程状态

Found one Java-level deadlock:
=============================

"thread=2":
  waiting to lock Monitor@0x00000000192b2598 (Object@0x00000000d5ea31b8, a com/xxx/testdemo/multhreadtest/Account),
  which is held by "thread=7"
"thread=7":
  waiting to lock Monitor@0x00000000192b1038 (Object@0x00000000d5ea30a8, a com/xxx/testdemo/multhreadtest/Account),
  which is held by "thread=9"
"thread=9":
  waiting to lock Monitor@0x00000000192b3cf8 (Object@0x00000000d5ea31a0, a com/xxx/testdemo/multhreadtest/Account),
  which is held by "thread=2"

Found a total of 1 deadlock.

Thread 1: (state = BLOCKED)


Thread 26: (state = BLOCKED)
 - com.rain.testdemo.multhreadtest.MulThreadTest1.run() @bci=270, line=56 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)


Thread 25: (state = BLOCKED)
 - com.rain.testdemo.multhreadtest.MulThreadTest1.run() @bci=91, line=41 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)


Thread 24: (state = BLOCKED)
 - com.rain.testdemo.multhreadtest.MulThreadTest1.run() @bci=270, line=56 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)


Thread 23: (state = BLOCKED)
 - com.rain.testdemo.multhreadtest.MulThreadTest1.run() @bci=91, line=41 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)


Thread 22: (state = BLOCKED)
 - com.rain.testdemo.multhreadtest.MulThreadTest1.run() @bci=91, line=41 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)


Thread 21: (state = BLOCKED)
 - com.rain.testdemo.multhreadtest.MulThreadTest1.run() @bci=270, line=56 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)


Thread 20: (state = BLOCKED)
 - com.rain.testdemo.multhreadtest.MulThreadTest1.run() @bci=270, line=56 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)


Thread 19: (state = BLOCKED)
 - com.rain.testdemo.multhreadtest.MulThreadTest1.run() @bci=270, line=56 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)


Thread 18: (state = BLOCKED)
 - com.rain.testdemo.multhreadtest.MulThreadTest1.run() @bci=270, line=56 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)


Thread 17: (state = BLOCKED)
 - com.rain.testdemo.multhreadtest.MulThreadTest1.run() @bci=91, line=41 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)


Thread 11: (state = IN_NATIVE)
 - java.net.SocketInputStream.socketRead0(java.io.FileDescriptor, byte[], int, int, int) @bci=0 (Interpreted frame)
 - java.net.SocketInputStream.socketRead(java.io.FileDescriptor, byte[], int, int, int) @bci=8, line=116 (Interpreted frame)
 - java.net.SocketInputStream.read(byte[], int, int, int) @bci=117, line=171 (Interpreted frame)
 - java.net.SocketInputStream.read(byte[], int, int) @bci=11, line=141 (Interpreted frame)
 - sun.nio.cs.StreamDecoder.readBytes() @bci=135, line=284 (Interpreted frame)
 - sun.nio.cs.StreamDecoder.implRead(char[], int, int) @bci=112, line=326 (Interpreted frame)
 - sun.nio.cs.StreamDecoder.read(char[], int, int) @bci=180, line=178 (Interpreted frame)
 - java.io.InputStreamReader.read(char[], int, int) @bci=7, line=184 (Interpreted frame)
 - java.io.BufferedReader.fill() @bci=145, line=161 (Interpreted frame)
 - java.io.BufferedReader.readLine(boolean) @bci=44, line=324 (Interpreted frame)
 - java.io.BufferedReader.readLine() @bci=2, line=389 (Interpreted frame)
 - com.intellij.rt.execution.application.AppMainV2$1.run() @bci=36, line=47 (Interpreted frame)


Thread 10: (state = BLOCKED)


Thread 9: (state = BLOCKED)


Thread 8: (state = BLOCKED)
 - java.lang.Object.wait(long) @bci=0 (Interpreted frame)
 - java.lang.ref.ReferenceQueue.remove(long) @bci=59, line=143 (Interpreted frame)
 - java.lang.ref.ReferenceQueue.remove() @bci=2, line=164 (Interpreted frame)
 - java.lang.ref.Finalizer$FinalizerThread.run() @bci=36, line=209 (Interpreted frame)


Thread 7: (state = BLOCKED)
 - java.lang.Object.wait(long) @bci=0 (Interpreted frame)
 - java.lang.Object.wait() @bci=2, line=502 (Interpreted frame)
 - java.lang.ref.Reference.tryHandlePending(boolean) @bci=54, line=191 (Interpreted frame)
 - java.lang.ref.Reference$ReferenceHandler.run() @bci=1, line=153 (Interpreted frame)

发现已经deadlock了 

修改如下:

public class MulThreadTest1 implements Runnable{
    private List<Account> accountList;
    Account firstInteger;
    Account secondInteger;
    volatile int flag1 = 0;
    volatile int flag2 = 0;


    public MulThreadTest1(List accountList){
        this.accountList = accountList;
    }
    @Override
    public void run() {
         int first;
         int second;
         int num;

            for(int i = 0;i < 100;i ++) {
                first = new Random().nextInt(20);
                second = new Random().nextInt(20);
                if(first == second){
                    if(second < 19){
                        second += 1;
                    }else {
                        second = 1;
                    }

                }
                firstInteger = accountList.get(first);
                if(flag1 == 0) {
                    flag1 = 1;
                    synchronized (firstInteger) {

                        num = new Random().nextInt(100);
                        if (firstInteger.getNum() - num < 0) {
                            i--;
                            continue;
                        }
                        System.out.println(Thread.currentThread().getName() + ",操作前:" + "账户:" + first + "=" + accountList.get(first).getNum() + "账户:" + second + "=" + accountList.get(second).getNum());

                        firstInteger.setNum(firstInteger.getNum() - num);

                        accountList.set(first, firstInteger);

                    }
                    flag1 = 0;
                    secondInteger = accountList.get(second);
                    if(flag2 == 0) {
                        flag2 = 1;
                        synchronized (secondInteger) {
                            secondInteger.setNum(secondInteger.getNum() + num);
                            accountList.set(second, secondInteger);
                            //accountList.set(first,accountList.get(first) -  num);
                            //accountList.set(second,accountList.get(second) +  num);
                            System.out.println(Thread.currentThread().getName() + ",操作:" + "账户:" + first + "=" + accountList.get(first).getNum() + "=>" + num + "=>" + "账户:" + second + "=" + accountList.get(second).getNum());
                        }
                    }
                }

                    flag2 = 0;

            }

    }
}

输出结果发现最终所有账户金额总额不是200000。

以上代码存在几个问题:

问题一:假如线程1对该对象进行操作时,从List中获取账户对象后,线程2也会从List中获取账户对象,然后当线程1抢到锁之前,线程2把线程1中的账户对象覆盖了,这样操作就有问题了。

问题二:假如线程1抢到了锁,并对账户1进行了操作,即将对账户2进行操作,此时发现flag2为1,那么此时线程1就会结束本次操作,这样线程1只对账户1进行了金额扣除,并没有回退操作,总金额就减少了。

问题三:设置两个flag值并不能防止死锁。当线程1锁了账户1,线程2锁了账户2,假设线程1和线程2同时制行了if(flag1==0),那么此时flag1并没有起到作用,之后线程1和线程2再次同时执行了if(flag2==0),线程1去对账户2操作,线程2去对账户1操作,发现都是锁着的,这就导致了死锁。

那么应该如何来防止以上死锁的情况呢?

只要打破造成死锁的条件即可,以上方案造成死锁的原因是同一个线程同时去抢占两个锁,这样很容易死锁,所以只要保证同一个线程同一个时刻只能获取一个锁这样就能避免死锁。

public class MulThreadTest3 implements Runnable{
    private List<Account> accountList;
    //Account firstInteger;
    //Account secondInteger;

    public MulThreadTest3(List accountList){
        this.accountList = accountList;
    }
    @Override
    public void run() {
         int first;
         int second;
         int num;

         for(int i = 0;i < 100;i ++) {
             first = new Random().nextInt(20);
             second = new Random().nextInt(20);
             if(first == second){
                 if(second < 19){
                     second += 1;
                 }else {
                     second = 1;
                 }
             }
             //System.out.println(Thread.currentThread().getStackTrace()+Thread.currentThread().getName());
             Account firstInteger = accountList.get(first);
             synchronized (firstInteger) {

                 num = new Random().nextInt(100);
                 if (firstInteger.getNum() - num < 0) {
                     i--;
                     continue;
                 }
                 System.out.println(Thread.currentThread().getStackTrace()[0].getMethodName()+Thread.currentThread().getName() + ",操作前:" + "账户:" + first + "=" + accountList.get(first).getNum() + "账户:" + second + "=" + accountList.get(second).getNum());

                 firstInteger.setNum(firstInteger.getNum() - num);
                 firstInteger.setThreadName(Thread.currentThread().getName());
                 accountList.set(first, firstInteger);
             }

             Account secondInteger = accountList.get(second);
             synchronized (secondInteger) {
                 secondInteger.setNum(secondInteger.getNum() + num);
                 firstInteger.setThreadName(Thread.currentThread().getName());
                 accountList.set(second, secondInteger);
                 //accountList.set(first,accountList.get(first) -  num);
                 //accountList.set(second,accountList.get(second) +  num);
                 System.out.println(Thread.currentThread().getStackTrace()[0].getMethodName()+Thread.currentThread().getName() + ",操作:" + "账户:" + first + "=" + accountList.get(first).getNum() + "=>" + num + "=>" + "账户:" + second + "=" + accountList.get(second).getNum());
             }

         }

    }
}

部分运行结果如下

getStackTracethread=0,操作前:账户:5=11323账户:19=9676
getStackTracethread=1,操作:账户:16=10083=>10=>账户:10=9543
getStackTracethread=0,操作:账户:5=11299=>24=>账户:19=9700
getStackTracethread=1,操作前:账户:11=10993账户:9=10525
getStackTracethread=0,操作前:账户:18=9344账户:1=9939
getStackTracethread=1,操作:账户:11=10983=>10=>账户:9=10535
getStackTracethread=0,操作:账户:18=9324=>20=>账户:1=9959
getStackTracethread=1,操作前:账户:10=9543账户:19=9700
getStackTracethread=0,操作前:账户:18=9324账户:10=9543
getStackTracethread=1,操作:账户:10=9522=>21=>账户:19=9721
getStackTracethread=0,操作:账户:18=9307=>17=>账户:10=9539
getStackTracethread=1,操作前:账户:19=9721账户:15=10155
getStackTracethread=1,操作:账户:19=9689=>32=>账户:15=10187
getStackTracethread=1,操作前:账户:3=10113账户:5=11299
getStackTracethread=1,操作:账户:3=10097=>16=>账户:5=11315
getStackTracethread=1,操作前:账户:13=9419账户:11=10983
getStackTracethread=1,操作:账户:13=9398=>21=>账户:11=11004
getStackTracethread=1,操作前:账户:5=11315账户:3=10097
getStackTracethread=1,操作:账户:5=11251=>64=>账户:3=10161
9280
9959
10004
10161
10641
11251
10040
8710
9800
10535
9539
11004
10635
9398
9814
10187
10083
9963
9307
9689
200000

总结

本题考察了多线程,以及多线程场景中锁的应用,如何避免死锁是关键,方案一虽然能很快解决本地,但是应该不是最理想的方案。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 好的,我可以为您讲解一下Java多线程下的银行存取钱的问题。 在银行存取钱的场景中,存在多个用户同时读取或修改同一个账户的情况。为了保证账户的正确性,需要使用多线程技术来解决这个问题。 下面是一个简单的Java多线程银行存取钱的示例: ```java public class BankAccount { private int balance; // 账户余额 public BankAccount(int balance) { this.balance = balance; } // 存钱 public synchronized void deposit(int amount) { balance += amount; System.out.println("存入:" + amount + ",余额为:" + balance); } // 取钱 public synchronized void withdraw(int amount) { if (balance >= amount) { balance -= amount; System.out.println("取出:" + amount + ",余额为:" + balance); } else { System.out.println("余额不足!"); } } } public class BankDemo { public static void main(String[] args) { BankAccount account = new BankAccount(1000); // 创建两个线程,一个存钱,一个取钱 Thread depositThread = new Thread(() -> { for (int i = 0; i < 5; i++) { account.deposit(100); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread withdrawThread = new Thread(() -> { for (int i = 0; i < 5; i++) { account.withdraw(200); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); // 启动线程 depositThread.start(); withdrawThread.start(); } } ``` 在上面的示例中,BankAccount类表示银行账户,包含了存钱和取钱的方法。这两个方法都使用了synchronized关键字来保证并发访问时的同步性。 在BankDemo类中,创建了两个线程来模拟存钱和取钱的过程。启动这两个线程之后,它们会同时对同一个账户进行操作,但是由于使用了synchronized关键字,所以不会出现数据不一致的情况。 当然,这只是一个简单的示例,实际应用中还需要考虑更多的情况,比如死锁、线程安全性等问题。 ### 回答2: Java 多线程可以用于实现银行的存取钱系统。在这个系统中,我们可以创建一个银行类(Bank),该类包含一个用于存储账户余额的变量(balance),以及提供存款(deposit)和取款(withdraw)方法。 在多线程环境下,每个用户(User)可以是一个线程。用户可以通过调用Bank类的存款和取款方法来存取钱。为了保证多个用户同时访问银行对象时的线程安全性,可以使用synchronized关键字对存款和取款方法进行同步。 下面是一个简单的示例代码: ```java public class Bank { private int balance; public Bank(int initialBalance) { this.balance = initialBalance; } public synchronized void deposit(int amount) { balance += amount; } public synchronized void withdraw(int amount) { if (balance >= amount) { balance -= amount; } else { System.out.println("余额不足"); } } public int getBalance() { return balance; } } public class User implements Runnable { private Bank bank; private String name; private boolean isDeposit; // 标记是否存款 public User(Bank bank, String name, boolean isDeposit) { this.bank = bank; this.name = name; this.isDeposit = isDeposit; } @Override public void run() { if (isDeposit) { bank.deposit(100); // 存款 System.out.println(name + " 存款后余额为:" + bank.getBalance()); } else { bank.withdraw(50); // 取款 System.out.println(name + " 取款后余额为:" + bank.getBalance()); } } } public class Main { public static void main(String[] args) { Bank bank = new Bank(0); User user1 = new User(bank, "用户1", true); User user2 = new User(bank, "用户2", false); Thread thread1 = new Thread(user1); Thread thread2 = new Thread(user2); thread1.start(); thread2.start(); } } ``` 在上述示例中,我们创建了一个银行对象bank,并使用两个用户(user1和user2)作为线程,一个存款,一个取款。通过Thread类的start方法,我们启动了这两个用户的线程,他们可以并发地操作银行对象。 当程序运行时,可能会出现以下结果的任何一种: ``` 用户1 存款后余额为:100 用户2 取款后余额为:50 ``` 或者 ``` 用户2 取款后余额为:0 用户1 存款后余额为:100 ``` 这是由于线程的执行顺序是不确定的,因此每次运行的结果可能会有所不同。 ### 回答3: Java多线程银行存取钱的实现可以通过以下方式: 1. 创建一个银行账户类BankAccount,包含账户余额属性和相关的操作方法,例如存款deposit()和取款withdraw()。 2. 创建一个银行类Bank,该类维护一个存储银行账户对象的列表,并提供操作方法,例如创建账户createAccount()和获取账户getAccount()等。 3. 创建一个多线程类ThreadBank,该类继承Thread类,重写run()方法,实现多个线程同时执行存取款操作。 4. 在run()方法中,使用synchronized关键字对BankAccount的存取款方法进行同步,以保证线程安全,并使用随机数生成器生成随机的存取款金额。 5. 在主函数中,创建Bank对象和一定数量的账户,然后创建一定数量的ThreadBank线程对象,并启动线程。 6. 主线程等待所有的线程执行完毕后,输出每个账户的最终余额信息。 具体的步骤如下: ```java // 银行账户类 class BankAccount { private double balance; public BankAccount(double balance) { this.balance = balance; } public double getBalance() { return balance; } public synchronized void deposit(double amount) { balance += amount; } public synchronized void withdraw(double amount) { if (balance >= amount) { balance -= amount; } else { System.out.println("余额不足"); } } } // 银行类 class Bank { private List<BankAccount> accounts; public Bank() { accounts = new ArrayList<>(); } public BankAccount createAccount(double balance) { BankAccount account = new BankAccount(balance); accounts.add(account); return account; } public List<BankAccount> getAccounts() { return accounts; } } // 多线程类 class ThreadBank extends Thread { private Bank bank; public ThreadBank(Bank bank) { this.bank = bank; } @Override public void run() { Random random = new Random(); List<BankAccount> accounts = bank.getAccounts(); for (int i = 0; i < 100; i++) { int accountIndex = random.nextInt(accounts.size()); BankAccount account = accounts.get(accountIndex); double amount = random.nextDouble() * 100; // 生成0-100之间的随机存取款金额 if (random.nextBoolean()) { account.deposit(amount); } else { account.withdraw(amount); } } } } public class Main { public static void main(String[] args) { Bank bank = new Bank(); BankAccount account1 = bank.createAccount(1000); BankAccount account2 = bank.createAccount(2000); List<ThreadBank> threads = new ArrayList<>(); for (int i = 0; i < 10; i++) { threads.add(new ThreadBank(bank)); } for (ThreadBank thread : threads) { thread.start(); } for (ThreadBank thread : threads) { try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } // 输出最终余额 System.out.println("账户1余额:" + account1.getBalance()); System.out.println("账户2余额:" + account2.getBalance()); } } ``` 通过运行上述代码,就可以模拟多个线程同时对银行账户进行存取款操作,并确保线程安全。最终输出每个账户的最终余额信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值