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 * http://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 */ 017package org.apache.commons.collections4.collection; 018 019import java.io.Serializable; 020import java.util.Collection; 021import java.util.Iterator; 022import java.util.Objects; 023import java.util.function.Predicate; 024 025/** 026 * Decorates another {@link Collection} to synchronize its behavior 027 * for a multithreaded environment. 028 * <p> 029 * Iterators must be manually synchronized: 030 * </p> 031 * <pre> 032 * synchronized (coll) { 033 * Iterator it = coll.iterator(); 034 * // do stuff with iterator 035 * } 036 * </pre> 037 * <p> 038 * This class is Serializable from Commons Collections 3.1. 039 * </p> 040 * 041 * @param <E> the type of the elements in the collection 042 * @since 3.0 043 */ 044public class SynchronizedCollection<E> implements Collection<E>, Serializable { 045 046 /** Serialization version */ 047 private static final long serialVersionUID = 2412805092710877986L; 048 049 /** 050 * Factory method to create a synchronized collection. 051 * 052 * @param <T> the type of the elements in the collection 053 * @param coll the collection to decorate, must not be null 054 * @return a new synchronized collection 055 * @throws NullPointerException if collection is null 056 * @since 4.0 057 */ 058 public static <T> SynchronizedCollection<T> synchronizedCollection(final Collection<T> coll) { 059 return new SynchronizedCollection<>(coll); 060 } 061 /** The collection to decorate */ 062 private final Collection<E> collection; 063 064 /** The object to lock on, needed for List/SortedSet views */ 065 protected final Object lock; 066 067 /** 068 * Constructor that wraps (not copies). 069 * 070 * @param collection the collection to decorate, must not be null 071 * @throws NullPointerException if the collection is null 072 */ 073 protected SynchronizedCollection(final Collection<E> collection) { 074 this.collection = Objects.requireNonNull(collection, "collection"); 075 this.lock = this; 076 } 077 078 /** 079 * Constructor that wraps (not copies). 080 * 081 * @param collection the collection to decorate, must not be null 082 * @param lock the lock object to use, must not be null 083 * @throws NullPointerException if the collection or lock is null 084 */ 085 protected SynchronizedCollection(final Collection<E> collection, final Object lock) { 086 this.collection = Objects.requireNonNull(collection, "collection"); 087 this.lock = Objects.requireNonNull(lock, "lock"); 088 } 089 090 @Override 091 public boolean add(final E object) { 092 synchronized (lock) { 093 return decorated().add(object); 094 } 095 } 096 097 @Override 098 public boolean addAll(final Collection<? extends E> coll) { 099 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}