View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.collection;
18  
19  import java.io.Serializable;
20  import java.util.Collection;
21  import java.util.Iterator;
22  import java.util.Objects;
23  import java.util.function.Predicate;
24  
25  /**
26   * Decorates another {@link Collection} to synchronize its behavior
27   * for a multithreaded environment.
28   * <p>
29   * Iterators must be manually synchronized:
30   * </p>
31   * <pre>
32   * synchronized (coll) {
33   *   Iterator it = coll.iterator();
34   *   // do stuff with iterator
35   * }
36   * </pre>
37   * <p>
38   * This class is Serializable from Commons Collections 3.1.
39   * </p>
40   *
41   * @param <E> the type of the elements in the collection
42   * @since 3.0
43   */
44  public class SynchronizedCollection<E> implements Collection<E>, Serializable {
45  
46      /** Serialization version */
47      private static final long serialVersionUID = 2412805092710877986L;
48  
49      /**
50       * Factory method to create a synchronized collection.
51       *
52       * @param <T> the type of the elements in the collection
53       * @param coll  the collection to decorate, must not be null
54       * @return a new synchronized collection
55       * @throws NullPointerException if collection is null
56       * @since 4.0
57       */
58      public static <T> SynchronizedCollection<T> synchronizedCollection(final Collection<T> coll) {
59          return new SynchronizedCollection<>(coll);
60      }
61      /** The collection to decorate */
62      private final Collection<E> collection;
63  
64      /** The object to lock on, needed for List/SortedSet views */
65      protected final Object lock;
66  
67      /**
68       * Constructor that wraps (not copies).
69       *
70       * @param collection  the collection to decorate, must not be null
71       * @throws NullPointerException if the collection is null
72       */
73      protected SynchronizedCollection(final Collection<E> collection) {
74          this.collection = Objects.requireNonNull(collection, "collection");
75          this.lock = this;
76      }
77  
78      /**
79       * Constructor that wraps (not copies).
80       *
81       * @param collection  the collection to decorate, must not be null
82       * @param lock  the lock object to use, must not be null
83       * @throws NullPointerException if the collection or lock is null
84       */
85      protected SynchronizedCollection(final Collection<E> collection, final Object lock) {
86          this.collection = Objects.requireNonNull(collection, "collection");
87          this.lock = Objects.requireNonNull(lock, "lock");
88      }
89  
90      @Override
91      public boolean add(final E object) {
92          synchronized (lock) {
93              return decorated().add(object);
94          }
95      }
96  
97      @Override
98      public boolean addAll(final Collection<? extends E> coll) {
99          synchronized (lock) {
100             return decorated().addAll(coll);
101         }
102     }
103 
104     @Override
105     public void clear() {
106         synchronized (lock) {
107             decorated().clear();
108         }
109     }
110 
111     @Override
112     public boolean contains(final Object object) {
113         synchronized (lock) {
114             return decorated().contains(object);
115         }
116     }
117 
118     @Override
119     public boolean containsAll(final Collection<?> coll) {
120         synchronized (lock) {
121             return decorated().containsAll(coll);
122         }
123     }
124 
125     /**
126      * Gets the collection being decorated.
127      *
128      * @return the decorated collection
129      */
130     protected Collection<E> decorated() {
131         return collection;
132     }
133 
134     @Override
135     public boolean equals(final Object object) {
136         synchronized (lock) {
137             if (object == this) {
138                 return true;
139             }
140             return object == this || decorated().equals(object);
141         }
142     }
143 
144     @Override
145     public int hashCode() {
146         synchronized (lock) {
147             return decorated().hashCode();
148         }
149     }
150 
151     @Override
152     public boolean isEmpty() {
153         synchronized (lock) {
154             return decorated().isEmpty();
155         }
156     }
157 
158     /**
159      * Iterators must be manually synchronized.
160      * <pre>
161      * synchronized (coll) {
162      *   Iterator it = coll.iterator();
163      *   // do stuff with iterator
164      * }
165      * </pre>
166      *
167      * @return an iterator that must be manually synchronized on the collection
168      */
169     @Override
170     public Iterator<E> iterator() {
171         return decorated().iterator();
172     }
173 
174     @Override
175     public boolean remove(final Object object) {
176         synchronized (lock) {
177             return decorated().remove(object);
178         }
179     }
180 
181     @Override
182     public boolean removeAll(final Collection<?> coll) {
183         synchronized (lock) {
184             return decorated().removeAll(coll);
185         }
186     }
187 
188     /**
189      * @since 4.4
190      */
191     @Override
192     public boolean removeIf(final Predicate<? super E> filter) {
193         synchronized (lock) {
194             return decorated().removeIf(filter);
195         }
196     }
197 
198     @Override
199     public boolean retainAll(final Collection<?> coll) {
200         synchronized (lock) {
201             return decorated().retainAll(coll);
202         }
203     }
204 
205     @Override
206     public int size() {
207         synchronized (lock) {
208             return decorated().size();
209         }
210     }
211 
212     @Override
213     public Object[] toArray() {
214         synchronized (lock) {
215             return decorated().toArray();
216         }
217     }
218 
219     @Override
220     public <T> T[] toArray(final T[] object) {
221         synchronized (lock) {
222             return decorated().toArray(object);
223         }
224     }
225 
226     @Override
227     public String toString() {
228         synchronized (lock) {
229             return decorated().toString();
230         }
231     }
232 
233 }