[concurrency-interest] private field

Jean Morissette jean.morissette666@videotron.ca
Wed, 13 Oct 2004 21:03:28 -0400


Thank for your reply.

David Holmes wrote:
>>Why fields in classes java.util.concurrent.* like LinkedBlockingQueue
>>are declared private instead of protected ?  It's very annoying.
> 
> 
> If the fields were protected then we'd be defining a subclassing contract
> that we would be forced to honor forever. fields should be internal
> implementation details.

I understand.

> So in general you won't find protected fields in library classes. Though in
> the absence of a security manager, I believe you can access private fields
> reflectively anyway.

I want to create a subclass for performance reason; using reflection 
will probably slow down performance, so it's not an option.

> What specifically do you want to achieve? There may be an alternative
> approach.

I want to use very fast queue for the SEDA framework.  One 
performance-critical method is to move all elements of the queue in a 
array.  A possible implementation could be:

public QueueElement[] drainToArray()
   synchronized (queue) {
     int qs = queue.size();
     if (qs == 0) return null;

     QueueElement[] result = new QueueElement[qs];
     for (int i = 0; i < qs; i++)
       result[i] = (QueueElementIF) queue.poll();
     }
     return result;
   }
}

This exemple is not efficient because we block the queue during the 
removal of the elements.  Here is another possibility:

public QueueElement[] drainToArray()
   Collection<QueueElement> c = new ArrayList<QueueElement>();
   queue.drainTo(c);
   return (QueueElement[]) c.toArray();
}

The method drainTo from LinkedBlockingQueue block only for a short 
amount of time.  So, if variable 'queue' is a LinkedBlockingQueue, this 
code provide very good concurrency. But, the problems are that we have 
to create a List each time, method toArray is time-consumming and 
finally, we don't know exactly the size of the queue, so it's possible 
that my ArrayList have to resize its underlying array (thus create an 
array and copy elements).

Imagine now if we could subclass LinkedBlockingQueue:

public Object[] drainToArray(Class arrayType) {

   Node first;
   fullyLock();
   try {
     int size = count.get();
     first = head.next;
     head.next = null;
     if (count.getAndSet(0) == capacity)
       notFull.signalAll();
     } finally {
       fullyUnlock();
     }

     // Transfer the elements outside of locks
     Object[] a = java.lang.reflect.Array.newInstance
                     (arrayType.getComponentType(), size);
     int n = 0;
     for (Node<E> p = first; p != null; p = p.next) {
       a[n] = p.item;
       p.item = null;
       ++n;
     }
     return a;
}

Here, we have all we want: concurrency, performance and low memory 
consumption.  I don't know how to achieve that without subclassing. Advice?

> David Holmes