-1

我在生产代码中遇到了一个突然的问题,自过去 5-6 年以来就没有发生过。我有一个线程池,它最多生成 64 个线程,所有 64 个线程都读取一些数据并将其放在一个公共中Map以供进一步处理。

读取是由来自特定源的所有线程完成的,我已经验证数据确实是从源读取的,但是,一个特定的批次没有被放入Map.

这是一个代码片段(由于保密问题,不能放整个代码):

try {
   <read the data>
    .
    .
    <do processing>
    .
    .
    synchronized(glock) { //glock is a class attribute, Object glock = new Object[];
     map.put(<data that was read>);
     log.debug("bla bla bla")
    }
} catch(Throwable e) { 
     log.error("error") 
  }
  finally {
    log.debug("done")
 }

ISSUE:特定线程不进入同步块,不放入映射,不打印"bla bla bla",不打印"error"但打印"done"

我已经验证了一切......代码中没有任何变化,这个问题突然出现了。问题是,我不能放任何额外的日志,因为它是生产代码,没有得到所有客户的同意,但这是最后一部分。

有没有人遇到过类似的问题,或者对此有所了解?正在读取的数据非常庞大,有 6000 条记录,每条记录至少有 0f 30-40 列数据。

提前致谢。

编辑:捕捉Throwable而不是Exception

4

2 回答 2

3

从您向我们展示的情况看来,

synchronized(glock){}

将数据放入地图时抛出异常,而不是打印“bla bla bla”。
“完成”被打印,因为它finallytry.

于 2012-08-13T11:47:27.020 回答
2

您的代码有 99% 的可能性有问题。这意味着synchronized块中的代码会引发异常,但您看不到它。

通常的罪魁祸首是:

  • 吞下异常的空catch块(可以在代码的其他地方)
  • 块中记录器的异常日志配置catch,例如,将异常写入不同的日志文件
  • 由于某种原因,日志消息没有按顺序写入(因此 ERROR 行不在您期望的位置)
  • 一些不寻常的情况(如内存不足)加上弹性代码会阻止写入日志消息。地图可能需要惊人的内存量。
  • log不是标准的 Java 记录器,而是别的东西。

您在 VM 中发现错误或存在硬件问题的可能性很小(< 1%)。如果您可以重复获得相同的结果,则可能不是硬件问题。

如果其他一切都失败了,您将需要在生产中调试问题。当然,您的客户会反对;那时,你会让他们决定哪个对他们更重要:一些规则,你不能调试代码或修复错误。

于 2012-08-13T12:11:23.137 回答