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

出力:

同期キーワードを入力しなかったため、出力は毎回異なり、次のようになります: (出力は正しく、まさに期待どおりです。正しい道を進んでいることを明確にしたいだけです。各スレッドは静的メソッドを呼び出す前に他のスレッドが終了するのを待たなければならないため、同期を使用するとプロセスが遅くなるため、同期を使用したくないためです)

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
4

2 に答える 2

4

JVM は、複数のスレッドによる呼び出しごとに、静的メソッドとそのローカル変数の新しいインスタンスをスタック (ヒープ上にあるオブジェクトを除く) に作成しますか?

はい、その通りです。

静的メソッドがローカル変数のみを参照する場合、自動的にスレッド セーフになります。(実際、これは非静的メソッドにも当てはまります。)

一般的に言えば、static可能であれば避けるべきだと思います。一般に、静的メンバーはある意味でグローバルであるため、コードのテストと推論が難しくなります。

于 2012-05-18T06:23:47.507 に答える
4

staticメソッドは問題ではなく、static変数のみがスレッド間で共有されます。

したがって、2つのスレッドが呼び出されます

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

問題が発生することはありません。

static int tmp;

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

あるスレッドが別の値を上書きする可能性があるため、マルチスレッドでは失敗しtmpます。

ローカル変数は、staticメソッド内であってもローカルであるため安全です。

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

于 2012-05-18T06:25:41.767 に答える