2

我是 Java 新手,在尝试实现一个简单的游戏时遇到了问题。目前游戏的前提是,使用计时器来添加汽车,并且更频繁地更新汽车的运动。一辆车可以通过触摸来选择,并通过绘制它的路径来引导。更新功能将沿着路径移动汽车。

现在,游戏因IndexOutOfBoundsException而崩溃,我几乎可以肯定这是因为偶尔,当重新选择汽车时,当前路径会被擦除,它允许绘制新路径。路径存储为LinkedList,并在汽车被触摸时清除。

我想如果通过触摸事件清除路径,而计时器线程正在更新汽车沿路径的移动,这就是发生错误的地方(两个线程访问这个列表时也可能出现类似的其他问题。

我的问题是,在 Java 中,处理这个问题的最佳方法是什么?是否应该使用特定类型的列表而不是 LinkedList,或者在 c++ 中是否存在诸如 Mutex 之类的对象,我可以在使用它的同时保护该列表?

4

2 回答 2

8

在 Java 中,这通常使用同步来完成

一个小例子可能看起来像这样:

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
    }
}

这两种方法可以有效地以相同的方式工作,但是使用第二种方法,您的线程安全被抽象为数据类型,这很好,因为当您使用列表时,您不必担心所有地方的线程安全。

于 2012-12-31T15:41:26.300 回答
0

您有几个内置选项,而不是重新创建自己的线程安全列表实现,本质上是:

  • 使用同步列表

    List list = Collections.synchronizedList(new LinkedList());
    

    请注意,您需要在列表(synchronized(list) { })上同步迭代和其他需要原子的组合操作)

  • 使用线程安全的集合,例如CopyOnWriteArrayListConcurrenLinkedQueue,如果您不需要访问列表中间的项目,而只需要添加一个迭代,这可能是一个不错的选择。

    请注意,根据您的用例,CopyOnWriteArrayList 可能会降低性能,特别是如果您定期添加项目(即每隔几微秒)并且列表可能会变大。

于 2013-01-01T08:03:51.677 回答