0

Java 7 でデスクトップ アプリを開発しています。ここに状況があります。以下の方法で

private synchronized void decryptMessage
    (CopyOnWriteArrayList<Integer> possibleKeys, ArrayList<Integer> cipherDigits)
{
    // apply opposite shift algorithm:
    ArrayList<Integer> textDigits = shiftCipher(possibleKeys, cipherDigits);

    // count CHI squared statistics:
    double chi = countCHIstatistics(textDigits);

    if(chi < edgeCHI) // if the value of IOC is greater or equal than that
    {
        System.err.println(chi + " " + possibleKeys + " +");
        key = possibleKeys; // store most suitable key
        edgeCHI = chi;
    }       
}

「chi」と呼ばれる値をカウントし、それに基づいて「chi」が「edgeCHI」値よりも小さい場合は、キーをインスタンス変数に保存します。そのメソッドは一部のスレッドによって呼び出されるため、同期を強制します。

すべてのスレッドが完了すると、一連の操作を制御するメソッドに制御を渡すことによって、プログラムの実行が続行されます。次に、この行がそのメソッドで実行されました。

System.err.println(edgeCHI+" "+key+" -"); 

methodで 'chi' の最後の値を出力したように、'chi' の正しい値を出力しますdecryptMessageが、key の値は異なります。キー値を生成するスレッドによって「decryptMessage」メソッドが呼び出されました。

キー値をグローバル変数として保存します private volatile CopyOnWriteArrayList<Integer> key = null; // stores the most suitable key for decryption。2 つの異なるキー値があるのはなぜですか? 値自体は重要ではありません。問題は、「decryptMessage」メソッド (chi < edgeCHI の場合) での最後の呼び出しで出力されたキーの値が、操作の流れを制御するメソッドで出力された値と一致する必要があることです。スレッドの作成方法は次のとおりです。

for(int y = 0; y < mostOccuringL.length; y++){// iterate through the five most frequent letters
                for(int i = (y + 1); i < mostOccuringL.length; i++ ){//perform letter combinations
                    int [] combinations = new int[2];
                    combinations[0] = y;
                    combinations [1] = i;                   
                    new KeyMembers(""+y+":"+i ,combinations, keywords, intKeyIndex, cipherDigits).t.join();
                }
            }   

run メソッド内で、 decryptMesssageメソッドを呼び出して、最も実現可能な復号化キーを特定します。2日間、何が問題なのかを理解しようとしてきましたが、わかりません。提案?

4

2 に答える 2

1

特にマルチスレッド環境では、実行順序を決定するために syserr (または sysout) の出力に依存することは危険です。印刷が実際にいつ行われるか、または印刷されたメッセージが適切であるかどうかは、まったく保証されません。スレッドの 1 つの "最後" に出力されたメッセージとして表示されるものは、キー フィールドを変更する "最後の" スレッドではなかった可能性があります。sterr の出力だけを見ても、そうは言えません。

あなたができることは、キーフィールドに同期セッターを使用することです。これにより、フィールドが変更されるたびに関連するアクセスカウンターが増加し、変更カウントとともに新しい値が出力されます。このようにして、syserr の出力の問題を回避し、最後に設定された値が何であったかを確実に判断できます。例:

private long keyModCount = 0;

private synchronized long update(CopyOnWriteArrayList<Integer> possibilities, double dgeChi) {
   this.keys = possibilites;
   this.edgeChi = edgeChi;   // how is edgeChi declared? Also volatile?
   this.keyModCount++;
   return this.keyModCount;
}

そして、decryptMessage 内:

if(chi < edgeCHI) // if the value of IOC is greater or equal than that
{
   long sequence = update(possibleKeys, chi); 
   System.err.println("["+ sequence +"]"+ chi + " " + possibleKeys + " +");
}   

答えを提供するには、スレッドの実行を制御する (必要に応じて単純化された) コードをもっと見る必要があります。

于 2012-09-27T21:37:31.457 に答える
0

解決策が見つかりました。フィールド変数が正しいキーを取得する時点で、CopyOnWriteArrayListデータ型を ArrayList に変更しました。現在、期待どおりに動作しています。

于 2012-10-02T16:48:30.540 に答える