【问题标题】:Writing a synchronized thread-safety wrapper for NavigableMap为 NavigableMap 编写同步的线程安全包装器
【发布时间】:2010-05-15 07:16:05
【问题描述】:

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

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

这里明显的遗漏是NavigableMap<K,V> 的实用方法。 extends SortedMap 确实如此,但 SortedSet extends SetSet extends CollectionCollections 也有专用于 SortedSetSet 的实用程序方法。大概NavigableMap 是一个有用的抽象,否则它一开始就不存在,但是没有实用方法。

所以问题是:

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

【问题讨论】:

    标签: java design-patterns collections synchronization wrapper


    【解决方案1】:

    这是一个疏忽。 The fix is in progress.

    乔希写道:

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

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

    这需要一些时间。

    更新:至于手动实现它,您可以考虑劫持java.util 包,因为您想扩展声明为私有包的static class SynchronizedSortedMap<K, V>。否则它将是大量的代码复制粘贴。下面是开场白:

    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 来源以获得见解:)

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

    【讨论】:

    • 哇!在“为什么?”方面具有权威性。不过,我现在不能接受这个答案,因为它缺少“如何?”。你会对此发表评论吗?这仍然是我问题的很大一部分。编写和测试这些“令人麻木的转发方法”有多难?不能半自动化吗?等等。
    • 我只需将static class SynchronizedMapstatic class SynchronizedSortedMapCollections 源中复制出来,添加您自己的SynchronizedNavigableMap 其中extends SynchronizedSortedMap 并以与两个复制的类相同的方式装饰缺少的方法做。这将是很多代码,已经很晚了:)
    • 这是一个机械的“头脑麻木”的过程!人们会认为它应该是可自动化的!
    【解决方案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. 使每个方法同步并委托给主体。

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

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

    【讨论】:

      【解决方案3】:

      Collections 没有为 NavigableMap 提供实用方法有什么具体原因吗?

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

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

      但无论哪种情况,原因并不重要。实用方法不存在,要么找第三方库,要么自己实现。

      一般来说你可以像这样添加同步线程安全特性是真的吗?

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

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

      不...见上文。

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

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

      【讨论】:

      • 只是为了澄清我自己的理解,这是Collections 对包装类所做的装饰器模式吗?例如synchronizedSet 返回一个 Set 以“装饰”另一个具有威胁安全功能的 Set,但它本身不做任何类似 Set 的工作?
      【解决方案4】:

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

      private NavigableMap&lt;Date,T&gt; map = Collections.synchronizedNavigableMap(...);

      Please see the Java8 Doc on Navigable Map

      【讨论】:

        猜你喜欢
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多