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