Java为高并发情况限制了非阻塞缓冲区

时间:2012-04-12 19:57:57

标签: java collections concurrency buffer guava

基本上我需要一个数据结构来存储服务器端的临时聊天消息。它应该是:

  • 有界:因为我不需要存储太多消息,客户端将每秒发送请求以获取新消息。我认为绑定大小应该是最大值。在一秒钟内挂载并发请求。当缓冲区已满时,旧消息将被删除。

  • 适合高并发访问:我不想使用像Collections.synchronizedXXXX这样的数据结构,因为在迭代期间,如果其他线程改变了数据结构,例如添加一条消息,它会抛出异常,所以我必须锁定整个数据结构,实际上我并不关心客户端请求是否可以获取最后插入的消息,因为它们会在一秒后发送一个新请求,另一方面,写操作应该永远不会延迟。 java.util.concurrency包下的类似乎是解决方案,但是......

  • 非阻塞:LinkedBlockingQueue,ArrayBlockingQueue它们可以被限制,并且在迭代期间不会抛出异常,但它们都是阻塞队列。当队列已满时,我想将新元素添加到尾部并从头部删除旧元素而不是阻塞它,并等待某人删除标题。

所以我的问题是第三个库有什么好的实现吗?比如谷歌番石榴? 或者您可能更了解如何在服务器上存储临时聊天消息?

非常感谢你!

5 个答案:

答案 0 :(得分:4)

您可以使用Apache Commons CircularFifoBuffer。它符合您的第一个和最后一个标准。要支持并发性,可以将基本缓冲区包装在其同步版本中,如下所示:

Buffer fifo = BufferUtils.synchronizedBuffer(new CircularFifoBuffer());

祝你好运。

答案 1 :(得分:4)

您可以将LinkedBlockingQueue与非阻止方法offer(或add)和poll一起使用来访问它。 您可以使用固定容量创建它以使其受限。

LinkedBlockingQueue<String> myStrings = new LinkedBlockingQueue<String>(100);
myStrings.offer("Hi!"); // returns false if limit is reached
myStrings.add("Hi, again!"); // throws exception if limit is reached
String s = myStrings.poll(); // returns null if queue is empty

答案 2 :(得分:3)

你看过ConcurrentLinkedQueue了吗? 页面上写着

  

此实现采用有效的“等待”算法......

等待自由是你可以获得的最强保证之一......

答案 3 :(得分:1)

您可以使用条件ArrayBlockingQueue语句将非阻塞行为添加到offer(),其中队列接受该商品的失败会导致头部被丢弃且商品被重新提供订做:

    public class LearnToQueue {


    public static void main(String[] args){
        Queue<Integer> FIFO = new ArrayBlockingQueue<Integer>(4);

        int i = 0;

        while ( i < 10 ){

            if (!FIFO.offer(i)){
            // You can pipe the head of the queue anywhere you want to
                FIFO.remove();
                FIFO.offer(i);
            }
            System.out.println(FIFO.toString());
            i++;

        }
    }

    }

答案 4 :(得分:0)

LinkedTransferQueue是一个阻塞的,无限制的队列,不强制执行严格的FIFO排序。它只会在从空队列中获取时阻止,但从不添加到一个队列。您可以通过添加尺寸或读取和放大来添加软帽以驱逐元素。写柜台。

根据您的要求,您可以编写自定义无锁环缓冲区。