001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.collections4.collection; 019 020import java.io.Serializable; 021import java.util.Collection; 022import java.util.Iterator; 023import java.util.Objects; 024import java.util.function.Consumer; 025import java.util.function.Predicate; 026 027/** 028 * Decorates another {@link Collection} to synchronize its behavior for a multithreaded environment. 029 * <p> 030 * Iterators must be manually synchronized: 031 * </p> 032 * 033 * <pre> 034 * synchronized (coll) { 035 * Iterator it = coll.iterator(); 036 * // do stuff with iterator 037 * } 038 * </pre> 039 * <p> 040 * This class is Serializable from Commons Collections 3.1. 041 * </p> 042 * 043 * @param <E> The type of the elements in the collection. 044 * @since 3.0 045 */ 046public class SynchronizedCollection<E> implements Collection<E>, Serializable { 047 048 /** Serialization version */ 049 private static final long serialVersionUID = 2412805092710877986L; 050 051 /** 052 * Creates a synchronized collection. 053 * 054 * @param <T> The type of the elements in the collection. 055 * @param coll The collection to decorate, must not be null. 056 * @return A new synchronized collection. 057 * @throws NullPointerException if collection is null. 058 * @since 4.0 059 */ 060 public static <T> SynchronizedCollection<T> synchronizedCollection(final Collection<T> coll) { 061 return new SynchronizedCollection<>(coll); 062 } 063 064 /** The collection to decorate */ 065 private final Collection<E> collection; 066 067 /** The object to lock on, needed for List/SortedSet views */ 068 protected final Object lock; 069 070 /** 071 * Constructs and wraps (not copies). 072 * 073 * @param collection The collection to decorate, must not be null. 074 * @throws NullPointerException if the collection is null. 075 */ 076 protected SynchronizedCollection(final Collection<E> collection) { 077 this.collection = Objects.requireNonNull(collection, "collection"); 078 this.lock = this; 079 } 080 081 /** 082 * Constructs and wraps (not copies). 083 * 084 * @param collection The collection to decorate, must not be null. 085 * @param lock The lock object to use, must not be null. 086 * @throws NullPointerException if the collection or lock is null. 087 */ 088 protected SynchronizedCollection(final Collection<E> collection, final Object lock) { 089 this.collection = Objects.requireNonNull(collection, "collection"); 090 this.lock = Objects.requireNonNull(lock, "lock"); 091 } 092 093 @Override 094 public boolean add(final E object) { 095 synchronized (lock) { 096 return decorated().add(object); 097 } 098 } 099 100 @Override 101 public boolean addAll(final Collection<? extends E> coll) { 102 synchronized (lock) { 103 return decorated().addAll(coll); 104 } 105 } 106 107 @Override 108 public void clear() { 109 synchronized (lock) { 110 decorated().clear(); 111 } 112 } 113 114 @Override 115 public boolean contains(final Object object) { 116 synchronized (lock) { 117 return decorated().contains(object); 118 } 119 } 120 121 @Override 122 public boolean containsAll(final Collection<?> coll) { 123 synchronized (lock) { 124 return decorated().containsAll(coll); 125 } 126 } 127 128 /** 129 * Gets the collection being decorated. 130 * 131 * @return The decorated collection. 132 */ 133 protected Collection<E> decorated() { 134 return collection; 135 } 136 137 @Override 138 public boolean equals(final Object object) { 139 synchronized (lock) { 140 if (object == this) { 141 return true; 142 } 143 return object == this || decorated().equals(object); 144 } 145 } 146 147 /** 148 * @since 4.6.0 149 */ 150 @Override 151 public void forEach(final Consumer<? super E> action) { 152 synchronized (lock) { 153 decorated().forEach(action); 154 } 155 } 156 157 @Override 158 public int hashCode() { 159 synchronized (lock) { 160 return decorated().hashCode(); 161 } 162 } 163 164 @Override 165 public boolean isEmpty() { 166 synchronized (lock) { 167 return decorated().isEmpty(); 168 } 169 } 170 171 /** 172 * Iterators must be manually synchronized. 173 * 174 * <pre> 175 * synchronized (coll) { 176 * Iterator it = coll.iterator(); 177 * // do stuff with iterator 178 * } 179 * </pre> 180 * 181 * @return An iterator that must be manually synchronized on the collection. 182 */ 183 @Override 184 public Iterator<E> iterator() { 185 return decorated().iterator(); 186 } 187 188 @Override 189 public boolean remove(final Object object) { 190 synchronized (lock) { 191 return decorated().remove(object); 192 } 193 } 194 195 @Override 196 public boolean removeAll(final Collection<?> coll) { 197 synchronized (lock) { 198 return decorated().removeAll(coll); 199 } 200 } 201 202 /** 203 * @since 4.4 204 */ 205 @Override 206 public boolean removeIf(final Predicate<? super E> filter) { 207 synchronized (lock) { 208 return decorated().removeIf(filter); 209 } 210 } 211 212 @Override 213 public boolean retainAll(final Collection<?> coll) { 214 synchronized (lock) { 215 return decorated().retainAll(coll); 216 } 217 } 218 219 @Override 220 public int size() { 221 synchronized (lock) { 222 return decorated().size(); 223 } 224 } 225 226 @Override 227 public Object[] toArray() { 228 synchronized (lock) { 229 return decorated().toArray(); 230 } 231 } 232 233 @Override 234 public <T> T[] toArray(final T[] object) { 235 synchronized (lock) { 236 return decorated().toArray(object); 237 } 238 } 239 240 @Override 241 public String toString() { 242 synchronized (lock) { 243 return decorated().toString(); 244 } 245 } 246}