java - 编程接口(interface)和同步集合

标签 java data-structures synchronization

这个问题与 Java 集合有关 - 特别是 Hashtable 和 Vector - 但也可能适用于其他地方。

我在很多地方都读到过针对接口(interface)编程有多好,我 100% 同意。例如,在不考虑底层实现的情况下针对 List 接口(interface)进行编程的能力肯定有助于解耦和测试目的。对于集合,考虑到内部存储结构、随机访问时间等方面的差异,我可以看到 ArrayList 和 LinkedList 如何在不同情况下适用。然而,这两个实现可以在同一接口(interface)下使用……很棒。

我似乎无法理解的是某些同步实现(特别是 Hashtable 和 Vector)如何适应这些接口(interface)。对我来说,他们似乎不适合这个模型。大多数底层数据结构实现似乎在数据存储方式(LinkedList、Array、排序树等)方面有所不同,而同步处理可以访问数据的条件(锁定条件)。让我们看一个示例,其中一个方法返回一个 Map 集合:

public Map<String, String> getSomeData();

让我们假设应用程序根本不关心并发性。在这种情况下,我们对方法通过接口(interface)返回的任何实现进行操作……大家都很高兴。世界是稳定的。

但是,如果应用程序现在需要关注并发方面怎么办?我们现在无法在不考虑底层实现的情况下进行操作 - Hashtable 会很好,但必须满足其他实现。让我们考虑 3 种情况:

1) 在添加/删除集合时使用同步块(synchronized block)等强制同步。但是,如果返回同步实现 (Hashtable),这会不会有点矫枉过正?

2) 更改方法签名以返回哈希表。然而,这将我们紧紧地绑定(bind)到 Hashtable 实现,因此,接口(interface)编程的优势被抛到了窗外。

3) 使用并发包并更改方法签名以返回 ConcurrentMap 接口(interface)的实现。对我来说,这似乎是前进的方向。

从本质上讲,某些同步实现似乎有点不适合集合框架,因为在对接口(interface)进行编程时,同步问题几乎迫使人们考虑底层实现。

我是否完全忽略了这里的重点?

谢谢。

最佳答案

1) 是的,这太过分了
2)正确,不应该这样做
3) 视情况而定。

事实是,如您所知,对接口(interface)的编程描述了应用程序做了什么(而不是它如何做,那是实现)

后续实现中去掉了同步(记住,Vector 和 Hastable 是在 java 1.2 之前的,后来 ArrayList 和 HasMap 没有同步,但是它们都分别实现了 List 和 Map 接口(interface)),因为它们会导致性能损失,因为过度同步。例如,如果您在单个线程中使用 vector ,您仍然会在该单个线程中获得同步。

设计应用程序时必须考虑在多个线程之间共享数据结构。您将在那里选择要使用的方法,并选择谁负责保持数据状态清洁。

您可以在此处选择您提到的选项 1 或选项 3。会有手动同步吗?我们应该使用同步接口(interface)吗?我们将支持什么版本等等。

例如,如果你选择 1,你也可以在你的设计中拒绝某些实现(即 vector )

数据同步不是靠“运气”发生的事情,您真的必须设计它才能正确发生并且不会导致它解决的问题更多。

在此设计过程中,您应该注意您将使用的选项(实现)和/或底层基础架构。

避免过度同步的最简单方法是使用不可变数据并且不要与其他线程共享您的数据。

与 Martin Fowler 的分布式计算第一定律非常相似:

"Hence, we get to my First Law of Distributed Object Design: Don't distribute your objects."

多线程应用的第一定律是:

First law of multithreaded applications: don't share your data?

:)

最后的注释:Collections类提供一些接口(interface)的“同步”版本:

Synchronized List
Synchronized Map
Synchronized Set

关于java - 编程接口(interface)和同步集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1591249/

相关文章:

java - 如何使用参数初始化 Java EE 5 JAX-WS 2.0 Web 服务

java - 使用 Java 向 HP 4515 打印机发送 PJL 命令

algorithm - 二叉搜索树中的顺序后继

php - PHP 中的 MPTT(修改后的预序树遍历)问题

mysql - 跨数据库同步 persistence_token

.net - PLINQ 是否尊重 SynchronizationContext?

java - 同步方法中的 for 循环

Java:创建大量新对象

java - 一个功能更丰富的数字(比 Bigdecimal)持有 java 库

java - 将一个字符串与多个字符串进行比较(最佳数据结构)