【问题标题】:What can I use instead of a Vector in Java? [duplicate]我可以用什么来代替 Java 中的 Vector? [复制]
【发布时间】:2011-03-08 22:19:15
【问题描述】:

看起来在使用 Java 编程时,如果涉及线程,我们将不再使用 Vectors。

在使用线程时我应该使用什么类而不是 Vector?

import java.util.Vector;
Vector<String> v = new Vector<String>();

【问题讨论】:

    标签: java multithreading vector thread-safety


    【解决方案1】:

    看起来在使用 Java 编程时,如果涉及线程,我们将不再使用 Vectors。

    您需要了解为什么使用Vector 在大多数情况下被认为是一件坏事。原因是:

    • Vector 同步每个操作。大多数上下文不需要细粒度同步,因此这是不必要的性能开销。

    • Vector.elements() 方法返回一个没有快速失败语义的 Enumeration

    回到你的问题。替代方案取决于您的线程试图做什么:

    • 如果用例根本不需要同步,请使用ArrayListLinkedList。在以下情况下,您通常会使用这些:

      • 列表是线程限制的;即只有一个线程可以访问它。
      • 列表需要粗粒度同步;即执行一系列操作时的独占访问。在这种情况下,您通常会创建一个自定义类,其中嵌入(例如)ArrayList,该类未在自定义类 API 中公开。
    • 如果用例需要细粒度同步,Collections.synchronizedList 包装器等效于Vector。或者,您可以坚持使用Vector 并避免使用elements() 操作。

    • CopyOnWriteArrayList 列表的优点是它的迭代器支持并发修改......在某种意义上。如果您的应用程序主要执行读取列表,它也可以更好地扩展。读取操作根本不需要显式同步,通常只需要读取单个volatile 一次。但另一方面是写操作确实是同步的,而且比“普通”ArrayList 更昂贵。

    VectorCollections.synchronizedList 包装器的另一个问题是某些用例需要更粗略的同步;例如测试列表的大小并在单个同步操作中有条件地添加元素。 QueueDeque 类提供了处理这种事情的更高级别的抽象......对于涉及将工作从一个线程异步传递到另一个线程的用例。


    最重要的是,没有一种万能的解决方案。您需要了解应用程序设计的并发特性,并据此选择数据结构。


    最后,如果您正在为 Java ME 编程,您可能无法使用 Vector,具体取决于您所针对的 J2ME 配置文件。

    【解决方案2】:
    List<String> list = Collections.synchronizedList(new ArrayList<String>());
    

    【讨论】:

    • 这是Vector 的或多或少的插件替代品。但它不一定是正确的使用方法。
    • 谢谢。我必须将我的一些向量转换为列表。
    【解决方案3】:

    对于线程不安全的情况,使用ArrayList

    对于线程安全的情况,请使用最适合您的情况,CopyOnWriteArrayListQueueBlockingDeque 等。要获得更多建议,我们需要知道您如何使用您的集合来操作。

    我建议不要使用 Collections.synchronizedList(...) 包装器,因为它可能无法很好地扩展(除非您不太关心可扩展性)。但这一切都取决于您的上下文。

    【讨论】:

    • 你能解释一下为什么Collections.synchronizedList(...) 不能扩展吗?
    • 如果您的使用模式是 99% 读取和 1% 写入,则 CopyOnWriteArrayList 提供更好的性能(阅读 COWAL javadoc)。但这一切都取决于使用模式。
    • 很公平 - 一个有趣的课程。我不是 100% 肯定我同意它(即它解决了可能通过使用更好的设计来解决的问题),但有时理想和实用是两件不同的事情。 +1
    • 我很小心,没有说这适用于所有场景,我认为这是非常重要的一点。更彻底地研究你的问题从来没有造成任何损害:)
    【解决方案4】:

    数组,但如果你不知道大小,请使用 concurrentmap 的实现

    【讨论】:

    • 假设您想要快速随机访问元素(这就是为什么 list 不是一个好主意)
    • 不同之处在于:Map 通过键提供随机访问,List 通过索引提供随机访问(或多或少有效)。
    • 你的意思是 map 提供 O(log(n)) 访问,而 List 提供 O(1)?然后它混淆了将其称为列表的讨论——它是一个伪装在列表接口中的数组。如果您知道大小,那么数组显然是最好的、最容易理解的选择。仅当您不知道您的选择是在地图或可增长数组之间选择的大小时,才能在多线程情况下提供一些不可预测的性能。
    【解决方案5】:

    使用列表并像同步它们一样

    List<?> list = Collections.synchronizedList(new ArrayList<?>());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-28
      相关资源
      最近更新 更多