用于get-size-and-delete-element模式的Java线程安全集合

时间:2013-01-08 07:05:16

标签: java multithreading collections concurrency

我有一个在多个线程之间共享的字符串列表。每个帖子必须:

  1. 访问列表(例如通过getter方法);
  2. 获取列表的大小;
  3. 在零和list.size();
  4. 之间选择一个随机数n
  5. 从列表中提取偏移量为n的元素;
  6. 从列表中删除提取的元素;
  7. “保存”列表,以便其他线程始终查看更新列表
  8. 由于可以同时访问可变共享对象(列表),因此我需要以线程安全的方式进行编码。每个线程必须将列表大小减少一个,因此每个其他线程访问必须看到一个较短的列表。我的目标是避免线程可以看到另一个线程看到的相同的列表,因为这样可能会提取相同的元素两次。

    实现这一目标的最佳方法是什么?我在考虑CopyOnWriteArrayList,但我不确定它是否像我需要的那样。

    谢谢

2 个答案:

答案 0 :(得分:7)

问题是操作1到6需要是原子的,使用CopyOnWriteArrayList不能解决这个问题。

一种解决方案是简单地同步整个操作:

private final List<String> list = new ArrayList<String> ();
public String getNextItem() {
    synchronized(list) {
        //get the string adn remove it from the list
    }
    return next;
}

或者,您可以查看您的算法并执行以下操作:

  • 创建列表
  • 洗牌(引入随机性)
  • 使用该列表填充BlockingQueue(例如LinkedBlockingQueue
  • 从队列中获取您的线程take items(线程安全原子操作=&gt;不需要额外的同步)

答案 1 :(得分:0)

我没有看到任何理由不能将上述逻辑序列放在同步块中,或者在上述逻辑序列中使用信号量/互斥量对列表进行独占访问。