从字段变量中读取值

时间:2012-09-27 20:20:09

标签: java multithreading field

我正在开发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 方法,以便识别最可行的解密密钥。 我一直试图弄清楚两天的问题是什么,但我不明白。 建议?

2 个答案:

答案 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。它现在按预期工作。