两个线程访问相同的LinkedList

时间:2012-12-31 15:37:36

标签: java android thread-safety

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

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

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

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

2 个答案:

答案 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)

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

  • 使用synchronized list

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

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

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

    请注意,根据您的使用情况,CopyOnWriteArrayList可能会降低性能,尤其是如果您经常添加项目(即每隔几微秒)并且列表可能会变大。