为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 Set
, Set extends Collection
,而Collections
则为SortedSet
和Set
提供了专用的实用方法。 据推测, NavigableMap
是一个有用的抽象,或者它首先不存在,但它没有实用的方法。
所以问题是:
-
Collections
没有为NavigableMap
提供实用程序方法的具体原因是什么? - 你会如何为
NavigableMap
编写自己的synchronized
包装器?- 浏览OpenJDK版本的
Collections.java
的源代码似乎表明这只是一个“机械”过程- 通常你可以像这样添加
synchronized
线程安全function吗? - 如果是这样一个机械过程,它可以自动化吗? (Eclipse插件等)
- 这个代码重复是必要的,还是可以通过不同的OOP设计模式来避免?
- 通常你可以像这样添加
- 浏览OpenJDK版本的
这是一种疏忽。 修复正在进行中 。
乔希写道:
“他们肯定属于那里。他们的缺席是无意的。
我们应该尽快把它们放进去。“我同意,即使我们工程师都没有期待编写(和测试)所有那些令人头脑麻木的转发方法。 发表日期: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
中。 再次,请参阅SynchronizedMap
和SynchronizedSortedMap
来源以获取见解:)
我不认为它(可能)是一个机械过程,因为它涉及很多因素。
通常你可以像这样添加同步的线程安全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插件等)
是的,我认为它很容易实现自动化。
- 实现界面
- 制作2个字段; 一个用于互斥,一个用于主题。
- 创建一个构造函数来注入主题。
- 使每个方法同步并委托给主题。
这个代码重复是必要的,还是可以通过不同的OOP设计模式来避免?
喜欢Set
, Map
等? 我听起来不可能以“正常”方式解决它。
Collections没有为NavigableMap提供实用程序方法的具体原因是什么?
我想不出具体的原因。 它是
- 疏忽
- 一个“几乎没有人会用它”的案例,或
- 也许有一些技术难度并不明显。
但在任何一种情况下,原因并不重要。 实用方法不存在,所以要么找到第三方库,要么自己实现。
通常,您可以添加这样的同步线程安全性function吗?
一般没有。 您需要了解要绑定的类的语义,以使线程安全,以确定包装器是否足够。
如果是这样一个机械过程,它可以自动化吗? (Eclipse插件等)
不……见上文。
这个代码重复是必要的,还是可以通过不同的OOP设计模式来避免?
我不认为这是可以避免的。 这种事情一般需要语言支持元编程,或者编写包装类的特定情况。 设计模式不适合你。
仅供参考,Java 8现在拥有它:
private NavigableMap
请参阅Navigable Map上的Java8 Doc