【发布时间】:2016-10-31 22:50:37
【问题描述】:
背景
我正在尝试使用 Apache Commons 库中的 CircularFifoBuffer 类,其中包含通过 WebSocket 连接接收到的最近消息的集合。但是,当我在 Linux 部署中达到 CircularFifoBuffer 的大小限制时,会抛出 BufferOverflowException。
我对 Java 还是很陌生,但我是这样定义 CircularFifoBuffer 实例变量的:
private static Buffer<String> recentWebSocketMessages = new CircularFifoBuffer<String>(1000);
这是一个例外:
org.apache.commons.collections15.BufferOverflowException: The buffer cannot hold more than 1000 objects.
at org.apache.commons.collections15.buffer.BoundedFifoBuffer.add(BoundedFifoBuffer.java:218)
at org.apache.commons.collections15.buffer.CircularFifoBuffer.add(CircularFifoBuffer.java:94)
at com.example.SystemMonitor.putRecentWebSocketMessage(SystemMonitor.java:228)
让我奇怪的是这个问题是间歇性的,当我写一个无限循环时:
while(true)
{
recentWebSocketMessages.add("TESTING");
}
没有发生异常(至少在 Windows 中——我还不能测试 Linux)
问题
所以我想这里的主要问题是为什么这个问题是间歇性的,我可以通过定义静态变量来解决这个问题吗? (即使这将recentWebSocketMessages 与BoundedFifoBuffer 的CircularFifoBuffer 实现紧密结合)
private static CircularFifoBuffer<String> recentWebSocketMessages = new CircularFifoBuffer<String>(1000);
编辑
感谢 sorifiend 和 Tom 指出这个实现不同步的简单事实。对于那些感兴趣的人,下面这个简单的线程示例证明了多线程是问题所在,同时访问缓冲区的多个线程可以/将导致 BufferOverflowException 发生(使用我对缓冲区的原始定义):
while(true)
{
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
recentWebSocketMessages.add("TESTING");
}
catch(BufferOverflowException e)
{
e.printStackTrace();
}
}
}).start();
}
具有以下recentWebSocketMessages 定义的相同代码不会抛出BufferOverflowException,因为对缓冲区的访问是同步的,如API 和sorifiend 的回答中所述:
Buffer recentWebSocketMessages = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(1000));
【问题讨论】:
-
"Note that this implementation is not synchronized." ... 可能是您的问题。
标签: java apache-commons circular-buffer