【发布时间】:2014-03-28 18:20:28
【问题描述】:
我在一个有 2 个线程、一个渲染线程和一个更新线程的 Android 应用程序中有一个共享的 java LinkedList。两个线程都在持续运行并不断迭代共享的 LinkedList。有时更新线程必须从 LinkedList 中删除一个对象。我如何对程序进行编码以保持多线程性能但允许这种情况发生。我不断从渲染线程收到 java.util.ConcurrentModificationException,因为我猜想在我尝试渲染它时该对象被删除了。
请注意,我在我的代码中使用了迭代器...
public void run()
{
if(Thread.currentThread() == renderThread)
{
while(true)
{
for(Iterator<GameObject> it = objects.iterator(); it.hasNext();)
{
it.next().render();
}
}
}
if(Thread.currentThread() == updateThread)
{
while(true)
{
for(Iterator<GameObject> it = objects.iterator(); it.hasNext();)
{
GameObject o = it.next();
it.next().update();
if(o.shouldBeRemoved())
it.remove();
}
}
}
}
一种可能的解决方案是捕获异常并忽略它,但我觉得这是骗子的出路,因为异常应该用于异常情况,而不是流。
【问题讨论】:
-
只需锁定(
synchronized)GameObject(不是整个列表),每个线程都在使用它。 -
您应该在列表上创建一个锁,因为那可能会遇到麻烦。即在迭代时从列表中删除一个元素。另外,我建议您使用 Synchronized 来锁定列表对象,而不是像上面那样进行线程比较。
-
或者你也可以使用线程安全列表。
-
我可以在您的代码中看到许多不同的缺陷:一种多用途方法用于两种不同的任务;共享状态的不正确同步;错误使用迭代器;两个线程都在繁忙的循环中运行......为什么实际上有两个不同的线程用于更新和渲染?只使用一个线程按顺序执行这两项操作。这可能不是最高效的解决方案,但它可以让您免于头疼!
-
@Matthew 您是否已经遇到过性能问题?您是否使用分析器来查找瓶颈?如果你想通过线程将更新和渲染分开,同步对象列表只是一件事。因为两个线程也会访问对象,所以它们的状态也必须同步。如果您不以巧妙的方式执行此操作(例如,通过使用受线程限制的快照),您将不会获得太多性能,而是会拥有一个复杂且容易出错的系统。当然是可行的,但我认为它需要更高的并发经验。
标签: java android multithreading linked-list thread-safety