Apache Commons - CircularFifoBuffer BufferOverflowException

时间:2016-10-31 22:50:38

标签: java apache-commons circular-buffer

背景

我正在尝试使用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)

问题

所以我想这里的主要问题是为什么这个问题是间歇性的,我可以通过定义静态变量来解决这个问题吗? (尽管这会将recentWebSocketMessagesCircularFifoBuffer的{​​{1}}实施紧密结合在一起

BoundedFifoBuffer

修改

谢谢sorifiend和Tom指出这个实现不同步的简单事实。对于那些感兴趣的人,下面这个简单的线程示例证明多线程是问题,多个线程同时访问缓冲区会导致private static CircularFifoBuffer<String> recentWebSocketMessages = new CircularFifoBuffer<String>(1000); 发生(使用我原来的缓冲区定义):

BufferOverflowException

具有以下while(true) { new Thread(new Runnable() { @Override public void run() { try { recentWebSocketMessages.add("TESTING"); } catch(BufferOverflowException e) { e.printStackTrace(); } } }).start(); } 定义的相同代码不会抛出recentWebSocketMessages,因为访问缓冲区的过程是在API和sorifiend的答案中提到的同步:

BufferOverflowException

1 个答案:

答案 0 :(得分:3)

快速回答:不,改变它就不会真的有帮助。

测试消息不会导致问题,因为应自动删除项目以添加空间:

  

CircularFifoBuffer是具有固定大小的先进先出缓冲区   如果已满,则替换最旧的元素。

     

CircularFifoBuffer的删除顺序基于插入   订购;元素的删除顺序与它们的顺序相同   添加。迭代顺序与删除顺序相同。

但是我相信当你处于缓冲区限制时(例如1000),当你的网络套接字使用多个线程时,有时会出现问题。

如果这是你的问题,那么打击它的最佳方法是同步它:

Buffer recentWebSocketMessages = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(1000));

而不是你现在如何做到这一点:

Buffer<String> recentWebSocketMessages = new CircularFifoBuffer<String>(1000);

复制表单API: https://commons.apache.org/proper/commons-collections/javadocs/api-3.2.2/org/apache/commons/collections/buffer/CircularFifoBuffer.html