并发帮助自定义类似队列的数据结构

时间:2016-05-30 15:54:39

标签: java multithreading data-structures concurrency

我正在尝试实现一个必须满足以下要求的以插入性能为中心的,类似队列的数据结构:

  1. 必须是线程安全的
  2. 必须能够在不同步的情况下添加到队列
  3. 必须能够获得队列的“快照”视图
  4. 我的问题是以不需要同步插入的方式获取“快照”视图。由于我可以阻止删除,并且元素只能添加到最后,因此获取元素不应成为问题。我一直遇到的问题是LinkedList的迭代器有一个不可压缩的并发修改快速失败,并且'LinkedList.get(int)'是O(n)。

    下面是一个简短的例子,说明我应该做一个相当简单的任务。

    public class SnapshotableQueue<T> {
        private final LinkedList<T> queue = new LinkedList<>();
        private final Object removeLock = new Object();
    
        public void add(T element) {
            queue.add(element);
        }
    
        public T remove() {
            synchronized(removeLock) {
                return queue.remove();
            }
        }
    
        public List<T> getSnapshot() {
            synchronized(removeLock) {
                int length = queue.size();
                List<T> snapshot = new ArrayList<>(length);
    
                ???
    
                return snapshot;
            }
        }
    }
    

    不可接受的解决方案#1

    for(int i = 0; i < length; i++)
        snapshot.add(snapshot.get(i));
    

    'LinkedList.get(int)'是O(n)

    不可接受的解决方案#2

    Iterator<T> iterator = queue.iterator();
    for(int i = 0; i < length; i++)
        snapshot.add(iterator.next());
    

    不是线程安全的(抛出ConcurrentModificationException)

    不可接受的解决方案#3

    Change queue to ArrayList
    

    'ArrayList.remove(0)'是O(n)

2 个答案:

答案 0 :(得分:3)

请勿重新发明轮子,使用ConcurrentLinkedQueue代替LinkedList,然后使用iterator()构建本机线程安全的快照。

您的方法getSnapshot将只是

public List<T> getSnapshot() {
    return new ArrayList<>(queue);
}

答案 1 :(得分:0)

Java CopyOnWriteArrayList中有一个它是并发包的一部分,似乎完全符合你的要求。

但请注意,每次插入内容时它都会创建列表的副本,因此只有在您阅读的内容比您编写的内容时才应该使用它。