It's all about expected usage patterns.

Locking in this case will be per instance and the likelihood of contention
is low given no one's going to call add a lot or indeed toString a lot in a
short space of time.

So given:

Define how concurrency is handled then implement

And assuming it's in line with the above contention model I'd say
synchronized would be adequate.

On 8 February 2011 14:54, Gregg Wonderly <gr...@wonderly.org> wrote:

> On 2/7/2011 5:28 PM, Peter Firmstone wrote:
>
>> Do we really need a concurrent version of this class? How often will Entry
>> classes change?
>>
>
> My choice is always to consider concurrency first, unless there is some
> element of performance that this impacts.  The simple fact is that there is
> a toString() that traverses the contents.  So, you either must synchronize
> all access to the contents, or use a CHM which solves the problem without
> any future concurrency surprises.
>
> I'm really serious about this, because of how I've encountered tons of
> "synchronized" blocks in river which introduce huge latency in "processing"
> because they cause everyone to wait in line for stuff which very often is
> quite independent.
>
> Yes, this structure is mostly one time mutated.  But, its design exposes a
> continuous mutation capability.  Thus, any "read" of the contents has to
> take that into account.
>
> Gregg Wonderly
>
>
>  Gregg Wonderly wrote:
>>
>>> Yes definitely the case. CHM just makes it a lot easier to not worry
>>> about map
>>> and set data structures in terms of concurrent access of mutating data.
>>> Set
>>> and HashSet are useful, but not always in concurrent mutating data
>>> management.
>>>
>>> I still prefer Vector over ArrayList just because it eliminates iteration
>>> problems that alway require the same lines of code to resolve.
>>>
>>> Gregg
>>>
>>> Sent from my iPhone
>>>
>>> On Feb 7, 2011, at 2:08 PM, Dan Creswell <dan.cresw...@gmail.com> wrote:
>>>
>>>  All true, still need to document the concurrent contract for this class
>>>> and
>>>> implement accordingly.
>>>>
>>>> i.e. We can say "toString" is thread safe etc and then use
>>>> ConcurrentHashMap
>>>> and friends.
>>>>
>>>> But we gotta do it right....
>>>>
>>>> On 7 February 2011 19:57, Gregg Wonderly <gr...@wonderly.org> wrote:
>>>>
>>>>  On 2/7/2011 5:24 AM, Tom Hobbs wrote:
>>>>>
>>>>>  Sorry, I've got my nit-picking hat on...
>>>>>>
>>>>>> The null check in the equals method isn't needed because you get a
>>>>>> free one by using "instanceof".
>>>>>>
>>>>>> I know you've warned that the class is not thread-safe, but people
>>>>>> often forget that doing a sysout of an object calls toString(). I'd
>>>>>> still be tempted to whack some protection into toString to stop it
>>>>>> blowing up when people start printing lots of debug messages.
>>>>>>
>>>>>> Other than that it looks good to me.
>>>>>>
>>>>>>  I'd suggest that it would be easy enough to just use
>>>>> ConcurrentHashMap
>>>>> instead of HashSet if we are going to move to Java 5 anyway. Then, you
>>>>> don't have to worry about concurrency issues with toString() etc.
>>>>>
>>>>> Gregg Wonderly
>>>>>
>>>>>
>>>>> On Mon, Feb 7, 2011 at 10:56 AM, Peter Firmstone<j...@zeus.net.au>
>>>>>
>>>>>> wrote:
>>>>>>
>>>>>>  Dan Creswell wrote:
>>>>>>>
>>>>>>>  Solid - probably ought to be a constructor that doesn't add defaults
>>>>>>>> too.....and maybe a note about thread safety on add.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>  The finished article.
>>>>>>>
>>>>>>> /*
>>>>>>> * Licensed to the Apache Software Foundation (ASF) under one
>>>>>>> * or more contributor license agreements. See the NOTICE file
>>>>>>> * distributed with this work for additional information
>>>>>>> * regarding copyright ownership. The ASF licenses this file
>>>>>>> * to you under the Apache License, Version 2.0 (the
>>>>>>> * "License"); you may not use this file except in compliance
>>>>>>> * with the License. You may obtain a copy of the License at
>>>>>>> *
>>>>>>> * http://www.apache.org/licenses/LICENSE-2.0
>>>>>>> *
>>>>>>> * Unless required by applicable law or agreed to in writing, software
>>>>>>> * distributed under the License is distributed on an "AS IS" BASIS,
>>>>>>> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>>>>>> implied.
>>>>>>> * See the License for the specific language governing permissions and
>>>>>>> * limitations under the License.
>>>>>>> */
>>>>>>>
>>>>>>> package org.apache.river.api.lookup;
>>>>>>>
>>>>>>> import java.util.HashSet;
>>>>>>> import java.util.Iterator;
>>>>>>> import java.util.Set;
>>>>>>> import net.jini.lookup.entry.Address;
>>>>>>> import net.jini.lookup.entry.Comment;
>>>>>>> import net.jini.lookup.entry.Location;
>>>>>>> import net.jini.lookup.entry.Name;
>>>>>>> import net.jini.lookup.entry.ServiceInfo;
>>>>>>> import net.jini.lookup.entry.Status;
>>>>>>> import net.jini.lookup.entry.UIDescriptor;
>>>>>>>
>>>>>>> /**
>>>>>>> * A little builder utility class that creates an array of Entry
>>>>>>> classes
>>>>>>> to
>>>>>>> * be used as a parameter for StreamServiceRegistrar. All the jini
>>>>>>> platform
>>>>>>> * Entry's are included by default.
>>>>>>> *
>>>>>>> * Note: This class is not threadsafe, use external synchronization if
>>>>>>> required.
>>>>>>> *
>>>>>>> * Suggested by Dan Creswell.
>>>>>>> * @author peter
>>>>>>> */
>>>>>>> public class DefaultEntries {
>>>>>>> private final Set<Class> entrys;
>>>>>>> public DefaultEntries() {
>>>>>>> entrys = new HashSet<Class>(16);
>>>>>>> }
>>>>>>> /**
>>>>>>> * Add an Entry class.
>>>>>>> * @param cl - class
>>>>>>> * @return this
>>>>>>> */
>>>>>>> public DefaultEntries add(Class cl){
>>>>>>> entrys.add(cl);
>>>>>>> return this;
>>>>>>> }
>>>>>>> /**
>>>>>>> * All all the Jini Platform Entry's
>>>>>>> * @return
>>>>>>> */
>>>>>>> public DefaultEntries addPlatformEntries(){
>>>>>>> add(Comment.class);
>>>>>>> add(Location.class);
>>>>>>> add(Name.class);
>>>>>>> add(ServiceInfo.class);
>>>>>>> add(Status.class);
>>>>>>> add(UIDescriptor.class);
>>>>>>> add(Address.class);
>>>>>>> return this;
>>>>>>> }
>>>>>>> /**
>>>>>>> * Remove all Entry's
>>>>>>> */
>>>>>>> public void reset(){
>>>>>>> entrys.clear();
>>>>>>> }
>>>>>>> /**
>>>>>>> * Generate a new array containing all Entry's added since last reset.
>>>>>>> * @return
>>>>>>> */
>>>>>>> public Class[] getEntries(){
>>>>>>> return entrys.toArray(new Class[entrys.size()]);
>>>>>>> }
>>>>>>>
>>>>>>> @Override
>>>>>>> public int hashCode() {
>>>>>>> int hash = 3;
>>>>>>> hash = 29 * hash + (this.entrys != null ? this.entrys.hashCode() :
>>>>>>> 0);
>>>>>>> return hash;
>>>>>>> }
>>>>>>>
>>>>>>> @Override
>>>>>>> public boolean equals(Object o){
>>>>>>> if (o == null) return false;
>>>>>>> if (o instanceof DefaultEntries){
>>>>>>> if (entrys.equals(((DefaultEntries)o).entrys)) return true;
>>>>>>> }
>>>>>>> return false;
>>>>>>> }
>>>>>>> @Override
>>>>>>> public String toString(){
>>>>>>> String newline = System.getProperty("line.separator");
>>>>>>> StringBuilder sb = new StringBuilder(256);
>>>>>>> sb.append("DefaultEntries:");
>>>>>>> sb.append(newline);
>>>>>>> Iterator<Class> it = entrys.iterator();
>>>>>>> while (it.hasNext()){
>>>>>>> sb.append(it.next().getName());
>>>>>>> sb.append(newline);
>>>>>>> }
>>>>>>> return sb.toString();
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>>
>>>
>>
>>
>

Reply via email to