【问题标题】:Apache Commons - CircularFifoBuffer BufferOverflowExceptionApache Commons - CircularFifoBuffer BufferOverflowException
【发布时间】: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)

问题

所以我想这里的主要问题是为什么这个问题是间歇性的,我可以通过定义静态变量来解决这个问题吗? (即使这将recentWebSocketMessagesBoundedFifoBufferCircularFifoBuffer 实现紧密结合)

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));

【问题讨论】:

标签: java apache-commons circular-buffer


【解决方案1】:

快速回答:不,这样更改并没有真正的帮助。

测试消息不会引起问题,因为应自动删除项目以增加空间:

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

一个 CircularFifoBuffer 的移除顺序是基于插入的 命令;元素以与它们相同的顺序被删除 添加。迭代顺序与移除顺序相同。

但我相信,当您处于缓冲区限制(在您的情况下为 1000)时,为 Web 套接字使用多个线程时有时会出现问题。

如果这是您的问题,那么解决它的最佳方法是像这样同步它:

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

而不是你现在的做法:

Buffer&lt;String&gt; recentWebSocketMessages = new CircularFifoBuffer&lt;String&gt;(1000);


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

【讨论】:

  • 优秀。考虑到我的应用程序绝对是多线程的,这很可能是根本原因。不敢相信我没有考虑到这一点。感谢您的详尽回答。
猜你喜欢
  • 1970-01-01
  • 2021-12-01
  • 2011-01-21
  • 2023-03-30
  • 2018-04-04
  • 2013-02-19
  • 2011-06-08
  • 2011-01-13
  • 1970-01-01
相关资源
最近更新 更多