当我们已经拥有向量时,为什么我们需要同步的ArrayLists?

时间:2010-01-20 20:31:45

标签: java

我们何时使用synchronized ArrayList?我们已经同步了Vector

5 个答案:

答案 0 :(得分:15)

我认为你错了。 ArrayList is unsynchronized, Vector is

同步意味着每个操作都是线程安全的 - 如果你同时使用两个线程中的相同向量,它们就不会破坏状态。但是,这会让它变慢。

如果您在单线程环境中工作(或者列表仅限于线程且从不共享),请使用ArrayList。如果您正在使用共享相同集合的多个线程,请使用Vector,或使用ArrayList,但以其他方式同步(例如,手动或通过包装器)。

答案 1 :(得分:4)

答案 2 :(得分:3)

ArrayList is not synchronized out of the box.

  

可调整大小的数组实现   列表界面。实现所有   可选列表操作和许可   所有元素,包括null。在   除了实施清单   接口,这个类提供方法   操纵数组的大小   用于内部存储的   名单。 (这个课程粗略   相当于Vector,除了它   是不同步的。)

在您知道不需要线程安全的情况下(例如,完全封装的私有数据),这可以避免一些性能问题。但是,当对它们使用迭代器时,ArrayList和Vector都有问题:当迭代任何类型的集合时,如果添加或删除了数据,you will throw a ConcurrentModificationException

  

请注意,此实现不是   同步。如果有多个线程   访问ArrayList实例   同时,至少有一个   线程修改列表   在结构上,它必须是同步的   外部。 (结构修改   是添加或删除的任何操作   一个或多个元素,或明确地   调整后备阵列的大小;仅仅   设置元素的值不是   结构修改。)这是   通常由...完成   同步一些对象   自然封装列表。如果不   这样的对象存在,列表应该是   “包裹”使用   Collections.synchronizedList方法。   这最好在创建时完成   防止意外不同步   访问列表:

     

列表清单=   Collections.synchronizedList(新   的ArrayList(...));

     

此类返回的迭代器   iterator和listIterator方法是   失败快速:如果列表是结构性的   之后随时修改   除了以外的任何方式创建迭代器   通过迭代器自己删除或   添加方法,迭代器将抛出一个   ConcurrentModificationException的。从而,   面对并发   修改,迭代器失败   快速而干净,而不是   冒着任意,不确定的风险   在一个不确定的时间的行为   未来。

     

注意一个快速失败的行为   迭代器无法保证   一般来说,是不可能的   做出任何艰难的保证   存在未同步的并发   修改。失败快速的迭代器   抛出ConcurrentModificationException   尽力而为。因此,它   写一个程序是不对的   依赖于这个例外   正确性:失败的快速行为   迭代器应该只用于   检测错误。

ArrayList有各种有用的风格,但是Vector没有。我个人最喜欢的是CopyOnWriteArrayList

  

ArrayList的线程安全变体,其中通过创建基础数组的新副本来实现所有可变操作(添加,设置等)。

     

这通常成本太高,但是当遍历操作大大超过突变时,它可能比替代方法更有效,并且当您不能或不想要同步遍历但需要排除并发线程之间的干扰时非常有用。 “快照”样式迭代器方法在创建迭代器时使用对数组状态的引用。这个数组在迭代器的生命周期中永远不会改变,所以干扰是不可能的,并且保证迭代器不会抛出ConcurrentModificationException。自迭代器创建以来,迭代器不会反映列表的添加,删除或更改。不支持对迭代器本身进行元素更改操作(删除,设置和添加)。这些方法抛出UnsupportedOperationException。

CopyOnWriteArrayLists在GUI工作中非常有用,特别是在您显示更新数据集(例如,在屏幕上移动图标)的情况下。如果您可以容忍显示的数据列表是一帧过时(因为您的生产者线程稍微落后于图形更新线程),CopyOnWriteArrayLists是完美的数据结构。

答案 3 :(得分:2)

  

在java中同步数组列表是什么意思?

这意味着它是线程安全的。

  • 矢量同步。任何触及Vector内容的方法都是线程安全的。
  • 另一方面,
  • ArrayList是不同步的,因此它们不是线程安全的。

答案 4 :(得分:0)

  

我读取ArrayList已同步   的java ..

the array list api

  

请注意,此实现不是   同步

因此,当您确定不会处理并发时,请使用ArrayList。 使用Vector可能是一种过度杀伤,可能会导致性能问题。