View Javadoc

1   package com.atlassian.plugin.util.concurrent;
2   
3   import java.util.Collections;
4   import java.util.HashMap;
5   import java.util.LinkedHashMap;
6   import java.util.Map;
7   import java.util.TreeMap;
8   import java.util.WeakHashMap;
9   
10  import com.atlassian.util.concurrent.CopyOnWriteMaps;
11  
12  /**
13   * A thread-safe variant of {@link Map} in which all mutative operations (the
14   * "destructive" operations described by {@link Map} put, remove and so on) are
15   * implemented by making a fresh copy of the underlying map.
16   * <p>
17   * This is ordinarily too costly, but may be <em>more</em> efficient than
18   * alternatives when traversal operations vastly out-number mutations, and is
19   * useful when you cannot or don't want to synchronize traversals, yet need to
20   * preclude interference among concurrent threads. The "snapshot" style
21   * iterators on the collections returned by {@link #entrySet()},
22   * {@link #keySet()} and {@link #values()} use a reference to the internal map
23   * at the point that the iterator was created. This map never changes during the
24   * lifetime of the iterator, so interference is impossible and the iterator is
25   * guaranteed not to throw <tt>ConcurrentModificationException</tt>. The
26   * iterators will not reflect additions, removals, or changes to the list since
27   * the iterator was created. Removing elements via these iterators is not
28   * supported. The mutable operations on these collections (remove, retain etc.)
29   * are supported but as with the {@link Map} interface, add and addAll are not
30   * and throw {@link UnsupportedOperationException}.
31   * <p>
32   * The actual copy is performed by an abstract {@link #copy(Map)} method. The
33   * method is responsible for the underlying Map implementation (for instance a
34   * {@link HashMap}, {@link TreeMap}, {@link LinkedHashMap} etc.) and therefore
35   * the semantics of what this map will cope with as far as null keys and values,
36   * iteration ordering etc. See the note below about suitable candidates for
37   * underlying Map implementations
38   * <p>
39   * There are supplied implementations for the common Collections {@link Map}
40   * implementations via the {@link CopyOnWriteMaps} static factory methods.
41   * <p>
42   * Collection views of the keys, values and entries are modifiable and will
43   * cause a copy.
44   * <p>
45   * <strong>Please note</strong> that the thread-safety guarantees are limited to
46   * the thread-safety of the non-mutative (non-destructive) operations of the
47   * underlying map implementation. For instance some implementations such as
48   * {@link WeakHashMap} and {@link LinkedHashMap} with access ordering are
49   * actually structurally modified by the {@link #get(Object)} method and are
50   * therefore not suitable candidates as delegates for this class.
51   * 
52   * @param <K> the key type
53   * @param <V> the value type
54   * @deprecated since 2.5.0 please use the
55   *             {@link com.atlassian.util.concurrent.CopyOnWriteMap} instead as
56   *             it has some important features and some bug fixes. This version
57   *             is no longer maintained.
58   */
59  @Deprecated
60  public abstract class CopyOnWriteMap<K, V> extends com.atlassian.util.concurrent.CopyOnWriteMap<K, V>
61  {
62      private static final long serialVersionUID = 7935514534647505917L;
63  
64      /**
65       * Creates a new {@link CopyOnWriteMap} with an underlying {@link HashMap}.
66       */
67      public static <K, V> CopyOnWriteMap<K, V> newHashMap()
68      {
69          return new CopyOnWriteMap<K, V>()
70          {
71              private static final long serialVersionUID = 5221824943734164497L;
72  
73              @Override
74              public <N extends Map<? extends K, ? extends V>> Map<K, V> copy(final N map)
75              {
76                  return new HashMap<K, V>(map);
77              }
78          };
79      }
80  
81      /**
82       * Creates a new {@link CopyOnWriteMap} with an underlying {@link HashMap}
83       * using the supplied map as the initial values.
84       */
85      public static <K, V> CopyOnWriteMap<K, V> newHashMap(final Map<? extends K, ? extends V> map)
86      {
87          return new CopyOnWriteMap<K, V>(map)
88          {
89              private static final long serialVersionUID = -7616159260882572421L;
90  
91              @Override
92              public <N extends Map<? extends K, ? extends V>> Map<K, V> copy(final N map)
93              {
94                  return new HashMap<K, V>(map);
95              }
96          };
97      }
98  
99      /**
100      * Creates a new {@link CopyOnWriteMap} with an underlying
101      * {@link LinkedHashMap}. Iterators for this map will be return elements in
102      * insertion order.
103      */
104     public static <K, V> CopyOnWriteMap<K, V> newLinkedMap()
105     {
106         return new CopyOnWriteMap<K, V>()
107         {
108             private static final long serialVersionUID = -4597421704607601676L;
109 
110             @Override
111             public <N extends Map<? extends K, ? extends V>> Map<K, V> copy(final N map)
112             {
113                 return new LinkedHashMap<K, V>(map);
114             }
115         };
116     }
117 
118     /**
119      * Creates a new {@link CopyOnWriteMap} with an underlying
120      * {@link LinkedHashMap} using the supplied map as the initial values.
121      * Iterators for this map will be return elements in insertion order.
122      */
123     public static <K, V> CopyOnWriteMap<K, V> newLinkedMap(final Map<? extends K, ? extends V> map)
124     {
125         return new CopyOnWriteMap<K, V>(map)
126         {
127             private static final long serialVersionUID = -8659999465009072124L;
128 
129             @Override
130             public <N extends Map<? extends K, ? extends V>> Map<K, V> copy(final N map)
131             {
132                 return new LinkedHashMap<K, V>(map);
133             }
134         };
135     }
136 
137     //
138     // constructors
139     //
140 
141     /**
142      * Create a new {@link CopyOnWriteMap} with the supplied {@link Map} to
143      * initialize the values.
144      * 
145      * @param map the initial map to initialize with
146      */
147     public CopyOnWriteMap(final Map<? extends K, ? extends V> map)
148     {
149         super(map);
150     }
151 
152     /**
153      * Create a new empty {@link CopyOnWriteMap}.
154      */
155     public CopyOnWriteMap()
156     {
157         super(Collections.<K, V> emptyMap());
158     }
159 }