多线程银行模拟

时间:2017-01-04 09:34:55

标签: java multithreading java-threads

此刻我正在玩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开始吧?

这是一个截图。

enter image description here

2 个答案:

答案 0 :(得分:0)

您描述的方案反映了您的帐户类中static个成员字段的使用情况。关键字static意味着字段不再是对象限制的,因为它们是类绑定的。因此,Account对象的每个实例都会在其任何实例上具有相同的static字段。

要解决此问题,您必须删除静态字段

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

答案 1 :(得分:0)

首先,在评论中提到它是Account类的错误名称。静态字段表示此字段依赖于类,而不依赖于对象(类的实例)。因此,您将在应用程序之间共享这些静态字段,这可能是多线程的好例子。

对于每个线程,for循环进行三次,因为它意味着

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

将为i = 0,i = 1和i = 2

调用它

如果你想使用共享资源进行多线程处理,在这个例子中我的建议是将Account类的名称更改为FamilyAccount,将Person更改为FamilyMember,并将其视为家庭成员的共享帐户。拥有一个帐户会有更多逻辑,然后您可以使用多线程并检查每个成员是否看到实际金额。

如果您要移除静态字段,我认为在多线程情况下没有任何意义。如果每个人都有一个帐户,并且他们作为一个线程工作,则不需要同步。

此外,您的Account类是Singleton的奇怪情况,其中有公共构造函数和getAcc方法,它总是返回相同的类实例。

我鼓励您查看和阅读有关交易和Singleton的信息,以便更好地理解案例。