如何迭代可由另一个线程添加的列表

时间:2014-09-18 02:12:09

标签: java multithreading concurrency

我有一个列表,我迭代并执行一些操作。其中一个可以执行的操作可能导致工作被传递给另一个线程,这可能会在我的列表中添加更多元素,而我仍在第一个线程中迭代它。

我有没有办法以这样的方式遍历列表:迭代器包含来自其他线程的添加?

这是一些伪Java

Class1{

   List multiThreadList = getMyList(); //points to list in Class2
   for(Element element:multiThreadList)
      //perform some actions, these actions may results in another thread being called
      //which will cause addToMyList() to be called while I'm still iterating over it
      //I want to keep iterating if an element gets added on the other thread
}
Class2{
   List originalList = new ArrayList();

   public getMyList()
     return originalList;

   void addToMyList(Element element)
     originalList.add(element);
}

2 个答案:

答案 0 :(得分:4)

你确定List是你需要的那种系列吗?

我会使用BlockingQueue,并在一个Thread中删除BlockingQueue中的元素,然后添加另一个。这样您就不需要任何额外的并发控制。

BlockingQueue<String> bounded   = new LinkedBlockingQueue<String>();

bounded.put("Value");

String value = bounded.take();

您的伪代码变为

Class1{

   BlockingQueue queue = getMyList();
   Object element = queue.poll(0, TimeUnit.SECONDS);
   while(element != null) {
      //perform some actions, these actions may results in another thread being called
      //which will cause addToMyList() to be called while I'm still iterating over it
      //I want to keep iterating if an element gets added on the other thread  
      element = queue.poll(0, TimeUnit.SECONDS);
   }
}
Class2{
   BlockingQueue originalList = new LinkedBlockingQueue();

   public BlockingQueue getMyList()
     return originalList;

   void addToMyList(Element element)
     originalList.put(element);
}

但有一点,您需要了解,当前形式的此任务会给您带来不一致的结果。由于你没有控制另一个Thread,你的迭代器可能会在添加新元素之前完成,并且你会在迭代时错过它,这取决于你可以从零到所有新元素的系统状态。因此,您需要在完成迭代之前加入所有创建的线程,或者更改方法。

答案 1 :(得分:0)

您必须使用某种类型的并发控制机制,例如Mutex锁,信号量或监视器。这些创建了代码的“关键部分”,一次只允许一个线程访问它。

不幸的是,如果不以某种方式锁定代码并将其中的一部分串行化,则无法解决问题。