我是Java新手,在尝试实现简单游戏时遇到了问题。 目前游戏的前提是,计时器用于添加汽车,并且还更频繁地更新汽车的运动。可以通过触摸选择汽车,并通过绘制它的路径来指示。更新功能将沿着路径移动汽车。
现在,游戏因 IndexOutOfBoundsException 而崩溃,我几乎可以肯定这是因为偶尔重新选择汽车时,会擦除当前路径,并允许绘制新路径。路径存储为 LinkedList ,并在触摸汽车时清除。
我想如果路径是通过触摸事件清除的,而定时器线程正在更新汽车沿路径的移动,这就是错误发生的地方(两个线程访问这个错误也会出现类似的其他问题列表。
我的问题,在Java中,处理这个问题的最佳方法是什么?是否有我应该使用的特定类型的列表而不是LinkedList,或者是否存在c ++中的Mutex等对象,我可以在使用它时保护此列表?
答案 0 :(得分:8)
在Java中,通常使用synchronization
来完成一个小例子可能看起来像这样:
LinkedList list = //Get/build your list
public void doStuffToList()
{
synchronized(list)
{
//Do things to the list
}
}
public void clearList()
{
synchronized(list)
{
list.clear();
}
}
如果此时列表中当前正在运行另一个线程,则此代码不会执行清除操作。请注意,这会导致阻塞,因此请注意死锁。
或者,如果您的List
是您自己构建的类,那么使数据结构线程本身安全可能是有意义的:
public class SynchroLinkedList
{
//Implementation details
public synchronized void doThingsToList()
{
//Implementation
}
public synchronized void clearList()
{
//Implementation
}
}
这两种方法可以有效地以同样的方式工作,但是使用第二种方法,您的线程安全性被抽象为数据类型,这很好,因为您在使用时不必担心线程安全清单。
答案 1 :(得分:0)
不是重新创建自己的线程安全列表实现,而是有几个内置选项,基本上是:
List list = Collections.synchronizedList(new LinkedList());
请注意,您需要在列表(synchronized(list) { }
)上进行同步,以进行迭代和其他需要原子化的组合操作。
使用线程安全集合,例如CopyOnWriteArrayList或ConcurrenLinkedQueue,如果您不需要访问列表中间的项目,这可能是一个不错的选择,但只需要添加一个迭代。
请注意,根据您的使用情况,CopyOnWriteArrayList可能会降低性能,尤其是如果您经常添加项目(即每隔几微秒)并且列表可能会变大。