简体   繁体   English

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

[英]Java bounded non-blocking buffer for high concurrent situation

Basically I need a data structure to store the temporary chatting messages on the server side. 基本上我需要一个数据结构来存储服务器端的临时聊天消息。 It should be: 它应该是:

  • bounded: because I don't need store too many messages, the client will send request to get the new messages every second. 有界:因为我不需要存储太多消息,客户端将发送请求以每秒获取新消息。 I think the bound size should be the max. 我认为绑定大小应该是最大值。 mount of concurrent requests in one second. 在一秒钟内挂载并发请求。 When the buffer is full, the old messages will be removed. 当缓冲区已满时,将删除旧消息。

  • suitable for high concurrent access: I don't want to use the data structure like Collections.synchronizedXXXX, because during the iteration, if other thread changes the data structure, eg adds a message, it will throw an Exception, so I have to lock the whole data structure, actually I don't really care if the client request can get the most last inserted message, because they will send a new request after one second, on the other side the write operation should be never delayed. 适合高并发访问:我不想使用像Collections.synchronizedXXXX这样的数据结构,因为在迭代期间,如果其他线程更改了数据结构,例如添加了一条消息,它将抛出异常,所以我必须锁定整个数据结构,实际上我并不关心客户端请求是否可以获得最后插入的消息,因为它们将在一秒钟后发送新请求,另一方面写操作应该永远不会延迟。 The classes under the package java.util.concurrency seems the solution, but... 包java.util.concurrency下的类似乎是解决方案,但是......

  • non-blocking: LinkedBlockingQueue, ArrayBlockingQueue they could be bounded and won't throw exception during iteration, but they are all blocking queue. 非阻塞:LinkedBlockingQueue,ArrayBlockingQueue它们可以有界并且在迭代期间不会抛出异常,但它们都是阻塞队列。 When the queue is full, I want to add the new element to the tails and remove the old element from head instead of blocking there and wait for someone to remove the header. 当队列已满时,我想将新元素添加到尾部并从头部删除旧元素而不是阻塞它并等待某人删除标题。

So my question is there any good implementation from 3rd library? 所以我的问题是第三个库有什么好的实现吗? For example Google Guava? 比如谷歌番石榴? Or maybe you have better idea about storing the temporary chatting messages on server? 或者您可能更了解在服务器上存储临时聊天消息?

thank you very much! 非常感谢你!

You could utilize the Apache Commons CircularFifoBuffer . 您可以使用Apache Commons CircularFifoBuffer It meets your first and last criteria. 它符合您的第一个和最后一个标准。 To support concurrency, you can wrap the base buffer in it's synchronized version like so: 要支持并发,可以将基本缓冲区包装在其同步版本中,如下所示:

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

Good luck on the project. 祝这个项目好运。

You can use LinkedBlockingQueue with the non-blocking methods offer (or add ) and poll to access it. 您可以使用LinkedBlockingQueue和非阻塞方法offer (或add )和poll来访问它。 You can create it with a fixed capacity to make it bounded. 您可以使用固定容量创建它以使其有界。

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

Did you take a look at ConcurrentLinkedQueue ? 你看过ConcurrentLinkedQueue了吗? The page says 该页面说

This implementation employs an efficient "wait-free" algorithm... 该实现采用有效的“等待”算法......

Wait-freedom is one of the strongest guarantee you can obtain.... 等待自由是你获得的最强保证之一....

You can add non-blocking behaviour to an ArrayBlockingQueue by surrounding it with a conditional offer() statement, where failure of the queue to accept the offer results in the head being dropped and the offer being re-made: 您可以通过使用条件offer()语句将其附加到ArrayBlockingQueue来添加非阻塞行为,其中接受该报价的队列失败会导致磁头被删除并且重新提供要约:

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

        }
    }

    }

LinkedTransferQueue is a blocking, unbounded queue that doesn't enforce strict FIFO ordering. LinkedTransferQueue是一个阻塞的无界队列,不强制执行严格的FIFO排序。 It will only block when taking from an empty queue, but never on adding to one. 它只会在从空队列中获取时阻止,但从不添加到一个队列。 You could add a soft cap to evict elements by adding either a size or read & write counters. 你可以通过添加一个大小或读写计数器来添加一个软帽来驱逐元素。

Depending on your requirements, you may be able to write a custom lock-free ring buffer. 根据您的要求,您可以编写自定义无锁环缓冲区。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM