简体   繁体   中英

Is there a concurrent circular linked queue collection in java?

I need to fetch data from the queue in a round-robin concurrent way. I am looking for a collection that implements such behavior. After some digging, I cannot find one. How would I implement one? I was looking at the ConcurrentLinkedQueue , but I am not sure how to make it circular. I need this collection to be highly performant.

I'm guessing I can do it with ConcurrentLinkedDeque . By using an iterator, I should be able to iterate all the way to the end, and once the end is reached I can re-create my iterator and go from the beginning.

=============================UPDATE===========================

Elements will be added to such collection by several threads during the initialization phase. Concurrent collection's state will be properly visible to the consumer threads that will be consuming one item at a time from it. Once the application is in a running state, elements won't be added to the collection. Only iteration and consumption of one element at a time by each thread in a cyclic fashion.

Given your revised question, this is what I would recommend:

For the initializing phase, use a concurrent Queue or Deque to accumulate the elements. Any implementation will do.

Once that phase is complete, create an instance of the following RoundRobin class from the queue object, and use its get method to the cycle through its elements.

public class RoundRobin <E> {
    private final AtomicInteger next = new AtomicInteger(0);
    private final E[] elements;

    public RoundRobin(Collection<E> queue, Class<E> clazz) {
        this.elements = queue.toArray(Array.newInstance(clazz, 0));
    }

    public E get() {
        return elements[next.getAndIncrement() % elements.length];
    }
}

The RoundRobin class is thread-safe and get is concurrent.

If the elements collection is mutated while you are constructing the RoundRobin , then the resulting RoundRobin state may not be the same as the final state of queue . From my reading of your stated requirements, that is OK.

What you are describing fits with a linked list, not a queue or deque. With a linked list, you could point the "next" node from the last element to point at the first. However, looking at Javadoc for LinkedList , there is no way to change where the last element points.

Note that if there was a way, you could create a synchronized view of that data structure by call Collections.synchronizedList() like this:

List<String> list = Collections.synchronizedList(new LinkedList<>());

For standard Java API, I don't think you can accomplish what you are trying to do. An option would be to implement your own data structure that extends List and allows you to alter where each node points so that you can make circular. Then use Collections.synchronizedList() to create a thread-safe view of it.

Note that Javadoc for Collections.synchronizedList() says: "It is imperative that the user manually synchronize on the returned list when iterating over it" and includes this example:

List list = Collections.synchronizedList(new ArrayList());
    ...
synchronized (list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
        foo(i.next());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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