2012-05-18 5 views
7

私はちょうどJavaの初心者であり、マルチスレッドアプリケーションに遭遇しました。私はこの質問がここのいくつかの記事に似ていることを知っていますが、私は私の質問に対してより良い答えを見つけることができませんでした。基本的には、静的メソッドにオブジェクトを渡したいのですが、そのメソッドはオブジェクトの値/プロパティに基づいて出力を返します。すべての呼び出しについて、私はオブジェクトの新しいインスタンスを作成しているので、メソッドの中のオブジェクトを変更する機会はまったくありません。さて、私の質問は、JVMは、静的メソッドとそのローカル変数の新しいインスタンスを、複数のスレッドが呼び出すたびにスタックに(オブジェクトをヒープ上に置くように)除外しますか?私が達成したいものを明確に表示するために、ここに私のコードです:オブジェクト参照を静的ヘルパーメソッドに渡す複数のスレッド

TestConcurrent.java

import classes.Player; 

public class TestConcurrent 
{ 
    private static int method(Player player) 
    { 
     int y = (player.getPoints() * 10) + 1; 

      try { 
        Thread.sleep(1000); 
      } catch (InterruptedException e) {} 

      return ++y; 
    } 

    public static void main(String[] args) throws Exception 
    { 
     // Create 100 threads 
     for(int i=1;i<=100;i++) 
     { 
      final int j = i; 
      // Create a new Thread 
      new Thread() 
      { 
       public void run() 
       { 
        // Create a new instance of the Player class 
        Player player = new Player(j,j,"FirstName" + j, "LastName" + j); 
        // Call static method() and pass a new instance of Player class 
        System.out.println("Thread " + j + ": " + TestConcurrent.method(player)); 
        // Check the values of the Player class after the call to the static method() 
        System.out.println("Player" + player.getAcctId() + " : Points=" + player.getPoints() + " Name=" + player.getFirstName() + " " + player.getLastName()); 
       } 
      }.start(); 
     } 
    } 

} 

Player.java

package classes; 

public class Player 
{ 
    private int acctId, points; 
    String firstName, lastName; 

    public Player(int acctId, int points, String firstName, String lastName) 
    { 
     this.acctId = acctId; 
     this.points = points; 
     this.firstName = firstName; 
     this.lastName = lastName; 
    } 

    public int getAcctId() { 
     return acctId; 
    } 
    public void setAcctId(int acctId) { 
     this.acctId = acctId; 
    } 
    public int getPoints() { 
     return points; 
    } 
    public void setPoints(int points) { 
     this.points = points; 
    } 
    public String getFirstName() { 
     return firstName; 
    } 
    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 
    public String getLastName() { 
     return lastName; 
    } 
    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 
} 

OUTPUT:

私はsynchronizedキーワードを入れていないので、th出力は毎回異なり、以下のようになります:(出力は正しいですが、まさに私が期待していることですが、私は正しいパスにあることを明確にしたいのですが、同期を使用したくないからです。それは、静的メソッドを呼び出すことができます前に、各スレッドが終了する他のスレッドを待つ必要がありますので、それは

Thread 2: 22 
Player8 : Points=8 Name=FirstName8 LastName8 
Thread 22: 222 
Thread 26: 262 
Thread 23: 232 
Player23 : Points=23 Name=FirstName23 LastName23 
Thread 21: 212 
Player21 : Points=21 Name=FirstName21 LastName21 
Thread 25: 252 
Player25 : Points=25 Name=FirstName25 LastName25 
Thread 20: 202 
Thread 19: 192 
Thread 24: 242 
Player24 : Points=24 Name=FirstName24 LastName24 
Player9 : Points=9 Name=FirstName9 LastName9 
Thread 28: 282 
+1

+1 - すばらしい最初の質問! StackOverflowへようこそ! – jmort253

答えて

4

は静的メソッドとその地元の新しいインスタンスを作成し、JVMます)プロセスが遅くなります複数のスレッドによるすべての呼び出しに対して、スタック内の変数(ヒープ上にあるオブジェクトを除く)

はい、そうです。

静的メソッドはローカル変数のみを参照する場合、自動的にスレッドセーフです。実際、非静的メソッドについても同様です。

一般的に言えば、可能ならばstaticを避けるべきです。一般的に、静的メンバーはグローバルであるという事実により、コードをテストするのが難しくなります。

+0

'static'メソッドは完全にうまく使用できます。たとえば、 'Math.min'です。 'Math.PI'のような定数もそうです。 最終的ではない 'static'変数だけを避けることで、あらゆる種類のマルチスレッドエラーが発生します。非常に速い応答のために –

+0

ありがとう。それは実際に私が達成したいものです。私はヘルパーメソッドが、いつでも呼び出し可能なグローバルメソッドのように動作するようにしたい。私の最初のデザインは実際にはメソッドが通常のクラスの内側にあり、各スレッドはクラスのインスタンスを作成してメソッドを呼び出します。私の実際の静的メソッドは、多くのロジックが内部で実行されていると私はそれの新しいインスタンスを作成するたびにパフォーマンスが心配です。上記のように、メソッドは渡されたオブジェクトを変更しません。私は静的メソッドを使用して、この方法を続けると良いでしょうか? –

+0

@PopoyMakisig、これは本当に難しい質問です。私は以前、ここでそこそこの便利なことをするために、私が一周しなければならない非常に中心的なクラスの「サーバー」というゲームを書きました。私はうんざりして静的メソッドを作成しました。最初はそれは大きな単純化のように見えましたが、結局私はその決定を後悔して元に戻りました。もし私があなただったら、私はそれを試してみて、それがどのように機能するかを見てみましょう。それが仕事をしてくれたら幸せにしてください、もしあなたが復帰したら、それをレッスンにしてください: – aioobe

4

staticの方法は問題ではなく、static変数だけがスレッド間で共有されます。

ので

public static int sum(int a, int b) { 
    int tmp = a + b; 
    return tmp; 
} 

を呼び出す2つのスレッドが問題に実行されません。あるスレッドがanothersをtmp値を上書きする可能性があるため

static int tmp; 

public static int sum(int a, int b) { 
    tmp = a + b; 
    return tmp; 
} 

は、マルチスレッドに失敗します。

staticメソッドであっても、ローカル変数はローカルなので安全です。

staticの方法を使用すると良いです。メソッドがオブジェクト変数にアクセスする必要がないことを強調しています。static定数を使用すると、エラーが発生しやすくなります。これを避けてください(また、変数にアクセスする必要がある場合は定数で同期を使用してください)。

+0

私のアプリケーションの目的のために、私は静的な非定数変数を使用するつもりはありません。定義された定数が必要な場合は、最終的な静的変数のみを使用しています。今のところすべては真っ直ぐです。 Javaの並行処理機能が既に私にはっきりと分かっている場合、私は同期メソッドやインスタンスメソッドを使用します。お返事をありがとうございます。 –

+0

この文章で私の人生を保存したばかりです。「静的メソッドでもローカル変数はローカルなので安全です。」私はこの答えに驚いています。それは直感的に間違っていると感じますが、良さには感謝しません! – aliteralmind

+0

コンパイラを使って作業しているときは、はっきりしているはずです。ローカル変数はスタックに格納されます。各スレッドは必ず独自のスタックを持っているため、それぞれのローカル変数を見ることはできません。実際、それらは現在のスタックポインタに相対的にアドレッシングされているので、同じスタックに複数のコピーがあるかもしれません。そうしないと、再帰も正しく動作しません。 –

関連する問題