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 */ 017package org.apache.commons.collections4.multiset; 018 019import java.util.Set; 020 021import org.apache.commons.collections4.MultiSet; 022import org.apache.commons.collections4.collection.SynchronizedCollection; 023 024/** 025 * Decorates another {@link MultiSet} to synchronize its behavior 026 * for a multithreaded environment. 027 * <p> 028 * Methods are synchronized, then forwarded to the decorated multiset. 029 * Iterators must be separately synchronized around the loop. 030 * </p> 031 * 032 * @param <E> The type held in the multiset. 033 * @since 4.1 034 */ 035public class SynchronizedMultiSet<E> extends SynchronizedCollection<E> implements MultiSet<E> { 036 037 /** 038 * Synchronized Set for the MultiSet class. 039 * 040 * @param <T> The type held in this Set. 041 */ 042 static class SynchronizedSet<T> extends SynchronizedCollection<T> implements Set<T> { 043 044 /** Serialization version */ 045 private static final long serialVersionUID = 20150629L; 046 047 /** 048 * Constructs a new instance. 049 * 050 * @param set The set to decorate 051 * @param lock The lock to use, shared with the multiset 052 */ 053 SynchronizedSet(final Set<T> set, final Object lock) { 054 super(set, lock); 055 } 056 } 057 058 /** Serialization version */ 059 private static final long serialVersionUID = 20150629L; 060 061 /** 062 * Factory method to create a synchronized multiset. 063 * 064 * @param <E> The type of the elements in the multiset 065 * @param multiset The multiset to decorate, must not be null 066 * @return A new synchronized MultiSet 067 * @throws NullPointerException if multiset is null 068 */ 069 public static <E> SynchronizedMultiSet<E> synchronizedMultiSet(final MultiSet<E> multiset) { 070 return new SynchronizedMultiSet<>(multiset); 071 } 072 073 /** 074 * Constructor that wraps (not copies). 075 * 076 * @param multiset The multiset to decorate, must not be null 077 * @throws NullPointerException if multiset is null 078 */ 079 protected SynchronizedMultiSet(final MultiSet<E> multiset) { 080 super(multiset); 081 } 082 083 /** 084 * Constructor that wraps (not copies). 085 * 086 * @param multiset The multiset to decorate, must not be null 087 * @param lock The lock to use, must not be null 088 * @throws NullPointerException if multiset or lock is null 089 */ 090 protected SynchronizedMultiSet(final MultiSet<E> multiset, final Object lock) { 091 super(multiset, lock); 092 } 093 094 @Override 095 public int add(final E object, final int count) { 096 synchronized (lock) { 097 return decorated().add(object, count); 098 } 099 } 100 101 /** 102 * Gets the multiset being decorated. 103 * 104 * @return The decorated multiset 105 */ 106 @Override 107 protected MultiSet<E> decorated() { 108 return (MultiSet<E>) super.decorated(); 109 } 110 111 @Override 112 public Set<Entry<E>> entrySet() { 113 synchronized (lock) { 114 final Set<MultiSet.Entry<E>> set = decorated().entrySet(); 115 return new SynchronizedSet<>(set, lock); 116 } 117 } 118 119 @Override 120 public boolean equals(final Object object) { 121 if (object == this) { 122 return true; 123 } 124 synchronized (lock) { 125 return decorated().equals(object); 126 } 127 } 128 129 @Override 130 public int getCount(final Object object) { 131 synchronized (lock) { 132 return decorated().getCount(object); 133 } 134 } 135 136 @Override 137 public int hashCode() { 138 synchronized (lock) { 139 return decorated().hashCode(); 140 } 141 } 142 143 @Override 144 public int remove(final Object object, final int count) { 145 synchronized (lock) { 146 return decorated().remove(object, count); 147 } 148 } 149 150 @Override 151 public int setCount(final E object, final int count) { 152 synchronized (lock) { 153 return decorated().setCount(object, count); 154 } 155 } 156 157 @Override 158 public Set<E> uniqueSet() { 159 synchronized (lock) { 160 final Set<E> set = decorated().uniqueSet(); 161 return new SynchronizedSet<>(set, lock); 162 } 163 } 164 165}