我正在开发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+" -");
它打印正确的'chi'值,因为已经在decryptMessage
方法打印了'chi'的最后一个值,但key的值是不同的。 'decryptMessage'方法已由生成键值的线程调用。
我将键值存储为全局变量
private volatile CopyOnWriteArrayList<Integer> key = null; // stores the most suitable key for decryption
。
为什么我有两个不同的键值?价值观本身并不重要。问题是在'decryptMessage'方法的最后一次调用时打印的密钥值(当chi&lt; 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 方法,以便识别最可行的解密密钥。 我一直试图弄清楚两天的问题是什么,但我不明白。 建议?
答案 0 :(得分:1)
依靠syserr(或sysout)打印来确定执行顺序是危险的 - 尤其是在多线程环境中。当打印实际发生或打印的消息有序时,绝对没有保证。也许您所看到的其中一个线程的“最后”打印消息不是修改关键字段的“最后”线程。你不能只通过查看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 + " +");
}
为了提供答案,我们需要查看更多(如果需要的话简化)代码来控制线程执行。
答案 1 :(得分:0)
已找到解决方案。我刚刚在字段变量获得正确密钥的位置将 CopyOnWriteArrayList 数据类型更改为ArrayList。它现在按预期工作。