java.util.Collections
currently provide the following utility methods for creating synchronized
wrapper for various collection interfaces:
synchronizedCollection(Collection<T> c)
synchronizedList(List<T> list)
synchronizedMap(Map<K,V> m)
synchronizedSet(Set<T> s)
synchronizedSortedMap(SortedMap<K,V> m)
synchronizedSortedSet(SortedSet<T> s)
Analogously, it also has 6 unmodifiedXXX
overloads.
The glaring omission here are the utility methods for NavigableMap<K,V>
. It's true that it extends SortedMap
, but so does SortedSet extends Set
, and Set extends Collection
, and Collections
have dedicated utility methods for SortedSet
and Set
. Presumably NavigableMap
is a useful abstraction, or else it wouldn't hav开发者_运维知识库e been there in the first place, and yet there are no utility methods for it.
So the questions are:
- Is there a specific reason why
Collections
doesn't provide utility methods forNavigableMap
? - How would you write your own
synchronized
wrapper forNavigableMap
?- Glancing at the source code for OpenJDK version of
Collections.java
seems to suggest that this is just a "mechanical" process- Is it true that in general you can add
synchronized
thread-safetiness feature like this? - If it's such a mechanical process, can it be automated? (Eclipse plug-in, etc)
- Is this code repetition necessary, or could it have been avoided by a different OOP design pattern?
- Is it true that in general you can add
- Glancing at the source code for OpenJDK version of
This was an oversight. The fix is in progress.
Josh writes:
"They definitely belong there. Their absence is unintentional.
We should put them in as soon as possible."I agree, even though none of us engineers are looking forward to writing (and testing) all those mind-numbing forwarding methods. Posted Date : 2006-08-21 00:50:41.0
It takes a time though.
Update: as to manually implementing it, you may consider to hijack the java.util
package since you would like to extend static class SynchronizedSortedMap<K, V>
which is declared package private. Else it's going to be a lot of code copypaste. Here's a kickoff:
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;
}
}
}
Let the IDE autogenerate the unimplemented methods of NavigableMap
and code them the same way as SynchronizedSortedMap
does. Here's ONE example:
@Override
public K ceilingKey(K key) {
synchronized (mutex) { return sm.ceilingKey(key); }
}
Note that the methods which returns for example Set
you'll need to wrap it in SynchronizedSet
as well. Again, see the SynchronizedMap
and SynchronizedSortedMap
sources for insights :)
I don't expect it to be (able to be) a mechanical process since it involves a lot of factors.
Is it true that in general you can add synchronized thread-safetiness feature like this?
I believe that is true. The definition of thread safety is (IMO),
A class is thread-safe if no incorrect behavior (that cannot occur when used from a single thread) can occur for all methods of it, when called from multiple-threads without any external synchronization.
Now, below code will ensure that "Something" is never called by multiple threads, right? Therefore, I believe no adverse behavior can emerge because of being called by multiple threads; It's never called from multiple threads!
This is probably also the idea behind EJB. Stateless EJBs are never called by more than one thread (enforced by the container). This is why the EJB spec can say "You don't have to worry about thread-safety".
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();
}
}
}
Or am I missing something?
To make the post complete:
Is there a specific reason why Collections doesn't provide utility methods for NavigableMap?
I agree with Stephen.
How would you write your own synchronized wrapper for NavigableMap?
Like my sample code..
Is it true that in general you can add synchronized thread-safetiness feature like this? If it's such a mechanical process, can it be automated? (Eclipse plug-in, etc)
Yeah I think it can easily be automated.
- Implement the interface
- Make 2 fields; One for the mutex, one for the subject.
- Create a constructor to inject subject.
- Make every method synchronized and delegate to subject.
Is this code repetition necessary, or could it have been avoided by a different OOP design pattern?
Like for Set
, Map
etc? It doesn't sound possible to me to solve it in a "normal" way..
Is there a specific reason why Collections doesn't provide utility methods for NavigableMap?
I cannot think of a specific reason. It is either
- an oversight,
- a case of "hardly anyone would use it", or
- maybe there is some technical difficulty that is not obvious.
But in either case, the reason doesn't really matter. The utility method is not there, so either you find a third-party library or implement it yourself.
Is it true that in general you can add synchronized thread-safetyness feature like this?
In general no. You need to understand the semantics of the class you are tying to make thread safe to figure out whether a wrapper is sufficient.
If it's such a mechanical process, can it be automated? (Eclipse plug-in, etc)
No ... see above.
Is this code repetition necessary, or could it have been avoided by a different OOP design pattern?
I don't think that it is avoidable. This kind of thing would require linguistic support for meta-programming in general, or for the specific case of writing wrapper classes. Design patterns don't do that kind of thing for you.
FYI, Java 8 now have it:
private NavigableMap<Date,T> map = Collections.synchronizedNavigableMap(...);
Please see the Java8 Doc on Navigable Map
精彩评论