2

オブジェクトを作成するたびに、識別子によって一意にアクセスできるようにしたいと考えています。増分静的値を使用して、作成されたオブジェクトの数を追跡し、新しいオブジェクトが構築されるたびに、その識別子を count + 1 と同等にします (そしてカウントをインクリメントします)。私が直面している問題は、同期が機能していないことです。コードの簡略版は次のとおりです。

public static final Hashtable MODULES = new Hashtable();
private static final Object countLock = new Object();
private static int count = 0;
private final String identifier;
private final String name;

public Class(String name) {
    this.identifier = String.valueOf(incrementCount());
    this.name = name;
    MODULES.put(identifier, name);
}

private static int incrementCount() {
     synchronized (countLock) {
        return ++count;
    }
}

これでテストすると(非現実的ですが、確かに、動作することを確認するために):

    for (int x = 0; x < 100; x++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Class m = new Class("Name");
            }
        }).start();
    }
    System.out.println(Module.MODULES.size());

60 年代から 100 年代までの出力が得られます。明らかに、この種の信頼性の低さは望ましくありません。揮発性フィールドはここで機能しますか? class(私は同じ結果を試しました)すべてのオブジェクトが異なる識別子を持っていることを確認する方法がわかりません。どんな解決策でも大歓迎です。

注: 実装固有の理由により、java.util.concurrent にはアクセスしません。

4

4 に答える 4

3

ロックは正常に機能していますが、問題は別のものです。new を介して各オブジェクトを初期化していますThreadスレッドがバックグラウンドで実行されている間、メイン スレッドは現在のカウントを出力します。間に適切な遅延を入れると、適切なカウントが表示されます。

public static void main(String[] args) throws InterruptedException{
    for (int x = 0; x < 100; x++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Counter m = new Counter("Name");
            }
        }).start();
    }
    Thread.sleep(1000);//put a delay
    System.out.println(MODULES.size());
}
于 2012-11-19T04:41:17.690 に答える
1

これを試して:

 for (int x = 0; x < 100; x++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Class m = new Class("Name");
            }
        }).start();
    }

    Thread.sleep(500);

    System.out.println(Module.MODULES.size());
于 2012-11-19T04:38:38.630 に答える
0

同期されていないハッシュテーブルのサイズを出力しています。ステートメント MODULES.put(identifier, name) の前に同期ステートメントを追加します。

synchronized (MODULES) {
        MODULES.put(identifier, name);
    }

わたしにはできる。

于 2012-11-19T04:41:18.280 に答える
0

あなたのコードの問題として私が見ているものは次のとおりです。ステートメントClass m = new Class("Name");は関数内にあり、コード内の の実装run()のコンストラクター内にはありません。Runnable

同様のコードを書く必要がある場合は、次のように書きます。

public class ModuleTest {

    public static void main(String[] args) {
    for (int x = 0; x < 100; x++) {
        new Thread(new Runnable() {
            {
                Module m = new Module("Name");
            }
            @Override
            public void run() {
                // do something
            }
        }).start();
    }
    System.out.println(Module.MODULES.size());
    }
}

上記のステートメントの配置を見てくださいModule m = new Module("Name");。が呼び出されたときに呼び出されるように、run()機能していません。そのステートメントは、コードにある匿名実装の構築中に呼び出される名前のない中かっこの間にあります。run()start(){}Runnable

上記のコードを完成させるためのModuleクラスは次のとおりです。

import java.util.Hashtable;

public class Module {

    public static final Hashtable MODULES = new Hashtable();
    private static final Object countLock = new Object();
    private static int count = 0;
    private final String identifier;
    private final String name;

    public Module(String name) {
        this.identifier = String.valueOf(incrementCount());
        this.name = name;
        MODULES.put(identifier, name);
    }

    private synchronized static int incrementCount() {
            return ++count;
    }
}
于 2012-11-19T10:43:54.250 に答える