2017-01-04 4 views
-1

現時点では、私はマルチスレッド化を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; 
    } 
} 

Accountクラス:

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

} 

Threadクラス:

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

} 

私が述べたように、それは例です私は見つけた異なる。これは動作しますが、正しくはありません。スレッドクラスでは、forループが各スレッドのコードを3回実行します。 もう1つの問題は、アカウントの残高がスレッドごとに変わらないことです。だから、私の最初のスレッドのための100の最終残高がある場合、2番目のものは、0からではなく100のバランスで開始します。 私は別のオブジェクトを持っている場合、それは0から始まるでしょうか?

ここにスクリーンショットがあります。

enter image description here

+3

「Account」クラスはどこにあるのか分かりませんが、ガベージであるため、行った本やウェブサイトのリンクを捨てます。良い非静的フィールドを持つ 'Person'クラスがありますので、あなたの銀行のために複数の' Person'オブジェクトを作成することができます。しかし、すべての 'static'フィールドを持つ' Account'クラスがあります。これはあなたのシステムに 'Account'しかないことを意味します。最大で1つの口座を持つ銀行は何ですか? 「静的」の総誤使用。それを燃やす!!! – Andreas

答えて

0

ご説明したシナリオは、あなたのAccountクラスでstaticメンバーフィールドの使用状況を反映しています。キーワードstaticは、フィールドがオブジェクトに限定されていないことを意味します。なぜなら、それらはクラスに限定されているからです。したがって、Accountオブジェクトのすべてのインスタンスは、そのインスタンス上で同じstaticフィールドを持ちます。あなたは、Accountクラスのために間違った名前で、コメントに記載されているよう

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

ありがとう、私は今それを修正しました。 –

+0

この例ではアカウントはまだシングルトンとして扱われていますが、これが問題を確実に解決するかどうかはわかりません –

0

にまず第一に、静的フィールドを削除する必要があり、それを修正するために

。静的フィールドとは、このフィールドがクラス依存であり、オブジェクト(クラスのインスタンス)に依存しないことを意味します。したがって、アプリケーション間で共有される静的フィールドを持つことになります。これは、マルチスレッドの良い例です。それは

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

に意図されているため、Forループ

は、あなたが一緒にプレイしたい場合は、I = 0、I = 1、I = 2

のために呼び出されるスレッドごとに3回行きます共有リソースを使ったマルチスレッドこの例では、アカウントクラスの名前をFamilyAccountに変更し、PersonをFamilyMemberに変更し、これを家族の共有アカウントとみなしています。 1つのアカウントを持つロジックが増え、マルチスレッドで遊ぶことができ、たとえばすべてのメンバーが実際の金額を確認できるかどうかを確認できます。

静的フィールドを削除する場合、マルチスレッドの場合は意味がないと思います。すべての人が1つのアカウントを持ち、1つのスレッドとして動作している場合は、同期の必要はありません。

また、あなたのAccountクラスは、publicコンストラクタとgetAccメソッドがあり、常にクラスの同じインスタンスを返す、シングルトンの奇妙なケースです。

大文字小文字の理解を深めるために、トランザクションとシングルトンについて見て読んでみることをお勧めします。