1

私がテストしているメソッド(xMethodと呼びましょう)を持つクラス(XClassと呼びましょう)があります。また、以下も含まれます。

private static Map<String, String> map = new HashMap<String, String>();

単体テストのセットアップ方法には次のものがあります。

ReflectionTestUtils.setField(xClass, "map", map, null);

テスト メソッドでは、いくつか (私の場合は 8 つ) のスレッドを作成します。run メソッドは xClass.xMethod を呼び出します。このメソッドは、静的マップ変数を変更します。メソッド xMethod は、map.containsKey()、map.get()、および map.put() を 8 回呼び出すことになっています。削除はしません。また、このメソッドは新しいスレッドを作成しないため、スレッドが xMethod で終了したら、マップを変更しないでください。すべてのスレッドが終了するのを待ちます (通常または例外によって)。地図を確認するより

int mapSize = map.size();
assertEquals("map:" + map, 8, mapSize);

ここで失敗し、次のメッセージが表示されます。

java.lang.AssertionError: マップ:{3=x1, 2=x2, 1=x3, 7=x4, 6=x5, 5=x6, 4=x7, 8=x8} 予想:<8> だった:< 7>

ConcurrentHashMap を使用して問題を解決しましたが、まだ問題に戸惑っています。8 つのスレッドがすべて終了した後、マップが奇妙な動作をする (size() は 7 を返すが、toString() は 8 つのエンティティを出力する) 可能性はありますか? 7 つのエンティティがあり、size() メソッドが 7 を返した場合は理解できましたが、マップには 8 つのエンティティがあります。これはどのように可能ですか?

ところで、私はいくつかの方法でスレッドの終了をチェックしまし
た: 1. Thread.State.TERMINATED をチェックします。
2.メソッドが戻る前に簡単なメッセージを出力し、スレッドが完了した後に簡単なメッセージを出力しました(そして、例外がスローされていないことを確認しました。8つのメッセージは常に9番目の前に書き込まれます(スレッドが「終了」した後のテストで)。
3. run メソッドに次のロジックを含む単純なスレッドを実行しました。

        public void run() {
                try {
                        obj = xClass.xMethod();
                } catch (Exception e) {
                        exc = e;
                }
                finished = true;
        }

すべてのスレッドが終了 == true になるまで、無期限にループするだけです。

これらはすべて、マップのアサートとチェックを続行する前に、スレッドが終了していることを意味します。それでは、どうすれば map.size() が 7 を返し、map.toString() が 8 つのエンティティを返すことができるのでしょうか?!

敬具、
デスポット

4

1 に答える 1

8

マップを同時に変更することにより、内部の不変条件を破壊し、予期された結果である未指定の予測不可能な動作を観察しています。

于 2013-01-16T14:58:23.347 に答える