为NavigableMap编写同步的线程安全包装器

java.util.Collections目前提供以下实用程序方法,用于为各种集合接口创建synchronized包装器:

  • synchronizedCollection(Collection c)
  • synchronizedList(List list)
  • synchronizedMap(Map m)
  • synchronizedSet(Set s)
  • synchronizedSortedMap(SortedMap m)
  • synchronizedSortedSet(SortedSet s)

类似地,它还有6个unmodifiedXXX重载。

这里明显的遗漏是NavigableMap的实用方法。 它确实extends SortedMap ,但SortedSet extends SetSet extends Collection ,而Collections则为SortedSetSet提供了专用的实用方法。 据推测, NavigableMap是一个有用的抽象,或者它首先不存在,但它没有实用的方法。

所以问题是:

  • Collections没有为NavigableMap提供实用程序方法的具体原因是什么?
  • 你会如何为NavigableMap编写自己的synchronized包装器?
    • 浏览OpenJDK版本的Collections.java的源代码似乎表明这只是一个“机械”过程
      • 通常你可以像这样添加synchronized线程安全function吗?
      • 如果是这样一个机械过程,它可以自动化吗? (Eclipse插件等)
      • 这个代码重复是必要的,还是可以通过不同的OOP设计模式来避免?

这是一种疏忽。 修复正在进行中 。

乔希写道:

“他们肯定属于那里。他们的缺席是无意的。
我们应该尽快把它们放进去。“

我同意,即使我们工程师都没有期待编写(和测试)所有那些令人头脑麻木的转发方法。 发表日期:2006-08-21 00:50:41.0

虽然需要一段时间。

更新 :关于手动实现它,您可能会考虑劫持java.util包,因为您希望扩展static class SynchronizedSortedMap ,它被声明为包私有。 否则它会成为很多代码复制品。 这是一个启动:

 package java.util; import java.util.Collections.SynchronizedSortedMap; public class NewCollections { public static  NavigableMap synchronizedNavigableMap(NavigableMap m) { return new SynchronizedNavigableMap(m); } static class SynchronizedNavigableMap extends SynchronizedSortedMap implements NavigableMap { private final NavigableMap sm; SynchronizedNavigableMap(NavigableMap m) { super(m); sm = m; } SynchronizedNavigableMap(NavigableMap m, Object mutex) { super(m, mutex); sm = m; } } } 

让IDE自动生成NavigableMap的未实现方法,并以与SynchronizedSortedMap相同的方式对它们进行编码。 这是一个例子:

  @Override public K ceilingKey(K key) { synchronized (mutex) { return sm.ceilingKey(key); } } 

请注意,返回的方法例如Set你也需要将它包装在SynchronizedSet中。 再次,请参阅SynchronizedMapSynchronizedSortedMap来源以获取见解:)

我不认为它(可能)是一个机械过程,因为它涉及很多因素。

通常你可以像这样添加同步的线程安全function吗?

我相信这是真的。 线程安全的定义是(IMO),

如果在没有任何外部同步的情况下从multithreading调用时,对于它的所有方法都不会发生不正确的行为(从单个线程使用时不会发生),则类是线程安全的。

现在,下面的代码将确保多个线程永远不会调用“Something”,对吧? 因此,我认为由于被multithreading调用,不会出现任何不利行为; 它永远不会从多个线程调用!

这可能也是EJB背后的想法。 无状态EJB永远不会被多个线程调用(由容器强制执行)。 这就是为什么EJB规范可以说“你不必担心线程安全”。

 public class MakeSomethingThreadSafe implements Something { private final Object lock = new Object(); private final Something subject; public MakeSomethingThreadSafe(Something subject){ this.subject = subject; } public void someMethod(){ synchronized(lock){ subject.someMethod(); } } } 

或者我错过了什么?

要完成post:

Collections没有为NavigableMap提供实用程序方法的具体原因是什么?

我同意斯蒂芬的观点。

你会如何为NavigableMap编写自己的同步包装器?

像我的示例代码..

通常你可以像这样添加同步的线程安全function吗? 如果是这样一个机械过程,它可以自动化吗? (Eclipse插件等)

是的,我认为它很容易实现自动化。

  1. 实现界面
  2. 制作2个字段; 一个用于互斥,一个用于主题。
  3. 创建一个构造函数来注入主题。
  4. 使每个方法同步并委托给主题。

这个代码重复是必要的,还是可以通过不同的OOP设计模式来避免?

喜欢SetMap等? 我听起来不可能以“正常”方式解决它。

Collections没有为NavigableMap提供实用程序方法的具体原因是什么?

我想不出具体的原因。 它是

  • 疏忽
  • 一个“几乎没有人会用它”的案例,或
  • 也许有一些技术难度并不明显。

但在任何一种情况下,原因并不重要。 实用方法不存在,所以要么找到第三方库,要么自己实现。

通常,您可以添加这样的同步线程安全性function吗?

一般没有。 您需要了解要绑定的类的语义,以使线程安全,以确定包装器是否足够。

如果是这样一个机械过程,它可以自动化吗? (Eclipse插件等)

不……见上文。

这个代码重复是必要的,还是可以通过不同的OOP设计模式来避免?

我不认为这是可以避免的。 这种事情一般需要语言支持元编程,或者编写包装类的特定情况。 设计模式不适合你。

仅供参考,Java 8现在拥有它:

private NavigableMap map = Collections.synchronizedNavigableMap(...);

请参阅Navigable Map上的Java8 Doc