2017-01-04 1 views
-1

In diesem Moment spiele ich mit Multi Threading in Java und ich bin mir nicht sicher, wie das funktioniert .. Ich habe das Gefühl, dass ich das in einem einfachen Beispiel im Internet gesehen habe, aber irgendwie Ich kann nicht verstehen, wie das in einer Banksimulations-App funktioniert, die ich aus dem Internet gefunden und verändert habe.Multi Threading Banksimulation

Hier ist, was ich habe:

Person Klasse:

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

Kontoklasse:

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){} 
    } 

} 

Thema Klasse:

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

} 

Wie ich bereits erwähnt, ist es ein Beispiel Ich fand und mo unterschieden. Das funktioniert aber nicht richtig, denke ich. In der Thread-Klasse geht die for-Schleife und führt den Code für jeden Thread 3 mal aus. Und ein weiteres Problem ist, dass der Kontostand für jeden Thread gleich bleibt. Also, wenn ich 100 Endabrechnung für meinen ersten Thread habe, startet die zweite gleich, mit 100 Balance und nicht von 0. Wenn ich verschiedene Objekte habe, sollte es von 0 anfangen, richtig?

Hier ist ein Screenshot.

enter image description here

+3

Ich weiß nicht, wo Sie diese "Account" -Klasse gefunden haben, aber werfen Sie den Buch- oder Website-Link weg, wo Sie das getan haben, denn es ist Müll. Sie haben eine "Person" -Klasse mit guten nicht statischen Feldern, so dass Sie mehr als ein "Person" -Objekt für Ihre Bank erstellen können. Aber dann hast du eine "Account" -Klasse mit allen "statischen" Feldern, was bedeutet, dass du immer nur einen "Account" in deinem System haben kannst. Was nützt eine Bank mit höchstens einem Konto? Totaler Missbrauch von "statisch". Verbrenne es !!! – Andreas

Antwort

0

Ihr beschriebene Szenario spiegelt die Verwendung von static Mitgliederfelder in Ihrem Konto-Klasse. Das Schlüsselwort static bedeutet, dass die Felder nicht mehr objektgebunden sind, da sie klassengebunden sind. So wird jede Instanz Ihres Account Objekts dasselbe Feld static über jede Instanz davon haben.

es beheben Sie die statischen Felder entfernen müssen

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

Danke, ich habe es jetzt behoben. –

+0

Sie sehen in diesem Beispiel Konto wird immer noch als Singleton behandelt, ich bin mir nicht sicher, ob dies Problem sicher lösen –

0

Zunächst einmal, wie es in den Kommentaren erwähnt wird, ist es falsch Name des Account-Klasse. Statisches Feld bedeutet, dass dieses Feld klassenabhängig und nicht objektabhängig ist (Instanz der Klasse). Sie werden also dieses statische Feld über die gesamte Anwendung verteilt haben, was ein gutes Beispiel für Multithreading sein kann.

For-Schleife geht dreimal für jeden Thread, weil es zu

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

gemeint ist, wird es für aufgerufen werden, i = 0, i = 1 und i = 2

Wenn Sie mit spielen wollen Multithreading mit freigegebenen Ressourcen Wie in diesem Beispiel mein Rat an Sie lautet, ändern Sie den Namen der Account-Klasse in FamilyAccount und Person in FamilyMember, und denken Sie darüber nach, wie ein gemeinsamer Account für Familienmitglieder. Es wird mehr Logik haben, ein Konto zu haben, und dann können Sie mit Multithreading spielen und prüfen, ob zum Beispiel jedes Mitglied den tatsächlichen Geldbetrag sieht.

Wenn Sie statische Feld entfernen, denke ich, dass es keinen Sinn im Falle von Multithreading haben wird. Wenn jede Person ein Konto hat und sie als ein Thread arbeiten, ist keine Synchronisierung erforderlich.

Auch Ihre Konto-Klasse ist seltsame Fall von Singleton, wo es öffentliche Konstruktor und getAcc-Methode gibt, die immer die gleiche Instanz der Klasse zurückgeben.

Ich ermutige Sie, über Transaktionen und Singleton zum besseren Verständnis des Falls zu lesen und zu lesen.