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

时间:2010-05-15 07:16:06

标签: java design-patterns collections synchronization wrapper

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

类似地,它也有6 unmodifiedXXX次重载。

这里明显的遗漏是NavigableMap<K,V>的实用方法。确实是extends SortedMapSortedSet extends SetSet extends CollectionCollections都有SortedSetSet的专用实用方法。据推测,NavigableMap是一个有用的抽象,否则它本来就不存在,但它没有实用的方法。

所以问题是:

  • Collections没有为NavigableMap提供实用方法的具体原因是什么?
  • 您如何为synchronized编写自己的NavigableMap包装器?
    • 瞥见source code for OpenJDK version of Collections.java似乎表明这只是一个“机械”过程
      • 一般情况下你可以像这样添加synchronized线程安全功能吗?
      • 如果是这样一个机械过程,它可以自动化吗? (Eclipse插件等)
      • 这个代码是否重复是必要的,还是可以通过不同的OOP设计模式来避免?

4 个答案:

答案 0 :(得分:4)

这是一种疏忽。 The fix is in progress

  

Josh写道:

     

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

     

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

虽然需要一段时间。

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

package java.util;

import java.util.Collections.SynchronizedSortedMap;

public class NewCollections {

    public static <K, V> NavigableMap<K, V> synchronizedNavigableMap(NavigableMap<K, V> m) {
        return new SynchronizedNavigableMap<K, V>(m);
    }

    static class SynchronizedNavigableMap<K, V> extends SynchronizedSortedMap<K, V> implements NavigableMap<K, V> {
        private final NavigableMap<K, V> sm;

        SynchronizedNavigableMap(NavigableMap<K, V> m) {
            super(m);
            sm = m;
        }

        SynchronizedNavigableMap(NavigableMap<K, V> 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来源获取见解:)

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

答案 1 :(得分:2)

  

通常你可以添加   同步线程安全功能   像这样?

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

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

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

这可能也是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();
        }
    }
}

或者我错过了什么?

要完成帖子:

  

是否有具体原因   集合不提供实用程序   NavigableMap的方法?

我同意斯蒂芬。

  

你会怎么写自己的   NavigableMap的同步包装器?

就像我的示例代码..

  

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

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

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

    此代码重复是否必要,或者   可以通过a避免它   不同的OOP设计模式?

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

答案 2 :(得分:1)

  

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

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

  • 疏忽,
  • “几乎没有人会使用它”的案例,或
  • 可能存在一些不明显的技术难题。

但无论如何,原因并不重要。实用方法不存在,所以要么找到第三方库,要么自己实现它。

  

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

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

  

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

不......见上文。

  

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

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

答案 3 :(得分:1)

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

private NavigableMap<Date,T> map = Collections.synchronizedNavigableMap(...);

Please see the Java8 Doc on Navigable Map