I have a class that implements Queue and draws values from other queues which may still be referenced outwith it. I want my method to draw values from the contained queues, using synchronized locks on them to ensure thread safety with other code that uses synchronized locks on the queues.
The way I've tried to achieve this is by having my method loop through all values indefinitely, storing the value if it's the next one, updating the stored values if it reaches the same queue again and the variables the queues are being measured by have changed since the list iteration, and returning the next value of the queue if it's unchanged since the last time it was checked and evaluated to have the next value - my logic being that at that point, all queues have been checked and the currently stored value/queue was checked earliest and has been reconfirmed to be the next value.
Is this the ideal way to create a thread-safe version of this method? Or would there be a better way?
Collection<Queue<T>> memberQueues;
final Lambda<T, Comparable> keyGetter;
public T get(boolean remove)
{
// workaround to ensure thread-safety when synchronized locks can't extend past the block they're declared in.
// Work on a copy of memberQueues
List<Queue<T>> memberQueuesCopy;
synchronized(memberQueues)
{ memberQueuesCopy = new ArrayList<Queue<T>>(memberQueues); }
// Declare variables and initialise with last member of memberQueuesCopy.
// If it checks every variable and the last one is next, then I don't think I need to check again.
Queue<T> nextQueue = memberQueuesCopy.get(memberQueuesCopy.size() - 1);
T nextValue = nextQueue.peek();
Comparable nextValueComparable = keyGetter.getMember(nextValue);
// Check all members of memberQueuesCopy. Find the lowest and hold the value until it gets to it again incase
// any values have changed. When it gets back to the current lowest value, check whether the value it's being
// sorted by has changed - and if it has, use its new values and run through all members again. If it hasn't,
// return it.
// I want a less contrived method. Suggestions that maintain thread safety?
for(;;)
{
for(Queue<T> i : memberQueuesCopy)
{
synchronized(i)
{
T iValue = i.peek();
Comparable iComparable = keyGetter.getMember(iValue);
if(i == nextQueue)
{
if(nextValue == iValue && nextValueComparable.equals(iComparable))
{
if(remove)
return nextQueue.remove();
else
return iValue;
}
nextValue = nextQueue.peek();
nextValueComparable = keyGetter.getMember(nextValue);
}
else
{
if(iComparable.compareTo(nextValueComparable) < 0)
{
nextQueue = i;
nextValue = iValue;
nextValueComparable = iComparable;
}
}
}
}
}
}