java多线程银行模拟

bbmckpt7  于 2021-07-09  发布在  Java
关注(0)|答案(2)|浏览(358)

现在我正在玩java中的多线程,我不知道它是如何工作的。。我觉得我在互联网上看到的一个简单的例子中理解了这一点,但不知何故,我无法理解这在我从互联网上找到并修改的银行模拟应用程序中是如何工作的。
以下是我所拥有的:
人员类别:

package threadsproject;

public class Person {

    private String name;

    public Person(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }
}

帐户类别:

package threadsproject;

public class Account {

    public static int balance;
    public static Account acc;
    private static Person p;

    public static int getBal(){
        return balance;
    }

    public void setBal(int bal){
        Account.balance = bal;
    }

    public static Account getAcc(Person p){
        if(acc == null){
            acc = new Account();
        }
        Account.p = p;
        return acc;

    }

    public synchronized void deposit(int val){
        try{

            if(val > 0){
                System.out.println("Person "+p.getName()+" is making a deposit.");
                try{
                    Thread.sleep(500);
                }catch(Exception e){}
                balance = balance + val;
                System.out.println("Person "+p.getName()+" completed the deposit.");
            }else{
                System.out.println("Can't deposit.");
            }
            System.out.println("Person "+p.getName()+" deposited "+val);

        }catch(Exception e){}
    }

    public synchronized void withdraw(int val){
        try{

            if(balance >= val){
                System.out.println("Person "+p.getName()+" is making a withdraw.");
                try{
                    Thread.sleep(500);
                }catch(Exception e){}
                balance = balance - val;
                System.out.println("Person "+p.getName()+" completed the withdraw.");
            }else{
                System.out.println("Can't withdraw.");
            }
            System.out.println("Person "+p.getName()+" withdrew "+val);

        }catch(Exception e){}
    }

}

螺纹等级:

package threadsproject;

import java.util.Scanner;

public class BankThread extends Thread implements Runnable{

    private Person p;

    public BankThread(Person p){
        this.p = p;
    }

    public void run(){
        for (int i = 0; i < 3; i++) {
            try {
                Account acc = Account.getAcc(p);
                Scanner s = new Scanner(System.in);
                System.out.println("Enter deposit ammount:");
                int dep = s.nextInt();
                acc.deposit(dep);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException ex) { }

                System.out.println("Enter withdrawal ammount:");
                int with = s.nextInt();
                if(with > Account.getBal()){
                    System.out.println("You don't have enough funds.");
                }else{
                    acc.withdraw(with);
                }
                System.out.println("Final balance: "+Account.getBal());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub

        Person p1 = new Person("Person1");
        Person p2 = new Person("Person2");
        Person p3 = new Person("Person3");
        BankThread bt1 = new BankThread(p1);
        bt1.start();
        bt1.join();
        BankThread bt2 = new BankThread(p2);
        bt2.start();
        bt2.join();
        BankThread bt3 = new BankThread(p3);
        bt3.start();
        bt3.join();
    }

}

正如我提到的,这是我发现并修改的一个例子。我认为这是可行的,但不正确。在threads类中,for循环执行每个线程的代码3次。另一个问题是每个线程的帐户余额保持不变。所以,如果我的第一个线程有100个最终余额,那么第二个线程也是这样开始的,100个余额,而不是从0开始。如果我有不同的对象,它应该从0开始,对吗?
这是一个截图。

dohp0rv5

dohp0rv51#

首先,正如评论中提到的,account类的名称是错误的。静态字段表示此字段依赖于类,而不是依赖于对象(类的示例)。所以您将在应用程序之间共享这些静态字段,这对于多线程来说是一个很好的例子。
for循环对每个线程执行三次,因为它意味着

for (int i = 0; i < 3; i++) {

它将在i=0、i=1和i=2时调用
如果您想使用共享资源进行多线程处理,那么在本例中,我的建议是将account类的名称更改为familyaccount,将person更改为familymember,并将其视为家庭成员的共享帐户。拥有一个帐户会有更多的逻辑,然后您可以使用多线程,并检查是否每个成员都看到了实际的金额。
如果您将删除静态字段,我认为它在多线程的情况下没有意义。如果每个人都有一个帐户,并且他们作为一个线程工作,那么就不需要同步。
另外,account类是一个奇怪的例子,其中有公共构造函数和getacc方法,它们总是返回类的同一个示例。
我鼓励您阅读和阅读有关事务和单例更好地理解的情况。

ffdz8vbo

ffdz8vbo2#

您描述的场景反映了 static 帐户类中的成员字段。关键字 static 意味着这些字段不再是对象有界的,因为它们是类有界的。所以你的每一个例子 Account 对象将具有相同的 static 它的任何示例上的字段。
要修复它,您必须删除静态字段

public static int balance;
 public static Account acc;
 private static Person p;

相关问题