2017-01-04 3 views
-1

В данный момент я играю с Multi Threading в java, и я не уверен, как это работает. Мне кажется, что я понял это на простом примере, который я видел в Интернете, но каким-то образом Я не могу понять, как это работает в приложении для банковского моделирования, которое я нашел и изменил из Интернета.Многопоточное банковское моделирование

Вот что у меня есть:

Person класс: класс

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(); 
    } 

} 

Как я уже говорил, это пример Я нашел и dified. Я думаю, это работает, но не правильно. В классе потоков цикл for проходит и выполняет код для каждого потока 3 раза. И еще одна проблема заключается в том, что баланс аккаунта остается неизменным для каждого потока. Итак, если у меня есть 100 окончательного баланса для моего первого потока, второй начинается с того же самого, с 100 балансом, а не с 0. Если у меня разные объекты, он должен начинаться с 0 правильно?

Вот скриншот.

enter image description here

+3

Не знаете, где вы нашли этот класс 'Account', но выбрасываете ссылку на книгу или сайт, где вы это делали, потому что это мусор. У вас есть класс «Лицо» с хорошими нестатическими полями, поэтому вы можете создать более одного объекта «Личность» для своего банка. Но тогда у вас есть класс 'Account' со всеми полями' static', что означает, что в вашей системе может быть только одна учетная запись. Что хорошего в банке с одним аккаунтом? Полное неправильное использование 'static'. Сожги это!!! – Andreas

ответ

0

Ваш описанный сценарий отражает использование static полей членов в классе Account. Ключевое слово static означает, что поля больше не ограничены объектами, потому что они ограничены классом. Таким образом, каждый экземпляр вашего объекта Account будет иметь такое же поле static над любым его экземпляром.

Чтобы исправить это, вы должны удалить статические поля

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

Спасибо, я исправил его сейчас. –

+0

Вы видите в этом примере Учетную запись по-прежнему обрабатывается как Singleton, я не уверен, что это наверняка разрешит проблему –

0

Прежде всего, как это упомянуто в комментариях это неправильное название для класса Account. Статическое поле означает, что это поле зависит от класса, а не от объекта (экземпляр класса). Таким образом, у вас будет такое статическое поле, совместно используемое в приложении, что может быть хорошим примером многопоточности.

Для цикла проходит три раза для каждого потока, так как она предназначена для

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

будет вызван для я = 0, г = 1 и я = 2

Если вы хотите, чтобы играть с многопоточность с разделяемыми ресурсами, как в этом примере, мой совет вам - изменить имя класса Account на FamilyAccount и Person to FamilyMember, и подумать об этом как об общей учетной записи для членов семьи. У него будет больше логики, чтобы иметь одну учетную запись, а затем вы можете играть с многопоточным чтением и проверять, если, например, каждый член видит фактическую сумму денег.

Если вы удалите статическое поле, я думаю, что это не будет иметь смысла в случае многопоточности. Если у каждого человека есть одна учетная запись, и они работают как один поток, нет необходимости в синхронизации.

Также ваш класс учетной записи - странный случай Singleton, где есть открытый метод Constructor и getAcc, который всегда возвращает тот же экземпляр класса.

Я предлагаю вам ознакомиться и прочитать о транзакциях и Singleton для лучшего понимания дела.

Смежные вопросы