Java queue with dynamic priority flag
Constants naming

CONSTANT_HUNDRED is a bad name. It tells us its value, but not its role. Its value could be changed, making the whole thing useless, and in addition it is used in completely different contexts (queue size, and time out delay) so a user wishing to change one, might unknowingly alter the other.

You should declare two distinct constants:

private static final int QUEUE_DEFAULT_SIZE = 100;
private static final int LOCK_TIMEOUT_MILLIS = 100;


Usage:

    this.queue = new PriorityQueue&lt;&gt;(QUEUE_DEFAULT_SIZE);
    ...
    if (this.lock.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {




Dubious Exception

When setting fetchByCustomPriority to false on a Queue which does not support custom priority, there will be an exception. There shouldn't be, because the user isn't asking for the unavailable functionality



Timing out breaks Queue contract

When timing out on pop(), you would return null. according to the Queue contract this null value means, "there are no Objects in the Queue now", but that may be wrong. It might just be that too many Threads are waiting to get their turn and this one got timed out.

You should Throw a custom TimedoutException to differentate between timing out, and having an empty queue.

Same goes for push().



Wrong usage of ternary operator ?

In peek:


return this.fetchByCustomPriority ? this.queue.peek() : (this.customPriorityQueue != null ? this.customPriorityQueue.peek() : null)



if the condition is true, the first member is returned, otherwise the second is returned. I suspect if fetchByCustomPriority is true, you'll want to use the customPriorityQueue, so you need to invert arguments 2 and 3.



Uneven popping

In push, you push messages on both queues.

In pop(), you either pop the queue, or the customPriorityQueue. This means both queues act differently depending on if fetchByCustomPriority is true or false. This makes your object inconsistent and breaks Queue interface contract:

ComparableQueueElement comparableQueue = new ComparableQueueElement(aComparator);
comparableQueue.push(element);
comparableQueue.setFetchByCustomPriority(true);
comparableQueue.pop(); // returns element
comparableQueue.setFetchByCustomPriority(false);
comparableQueue.pop(); // returns element AGAIN!!


Your objects should stay consistent.

You could fix this by popping both queues in pop() method.

Or you could design your functionality in a way that it cannot fail...



Infallible DynamicPriorityQueue

Your fields are too rich for your object. The two queues could become out of sync. The best way to fix this is to have your objects only allow states which make sense.

Since you're describing an Object wich is a queue, let the only field by a queue.
I've changed to class to make it a bit more dynamic even, in that the comparator is no longer a fixed one. So now your can setFetchByCustomPriority(null) to fetch in-order, or setFetchByCustomPriority(comparatorA) and switch to setFetchByCustomPriority(comparatorB) on the fly.

import javax.naming.OperationNotSupportedException;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class DynamicPriorityQueue&lt;ComparableQueueElement&gt; implements IQueue&lt;ComparableQueueElement&gt; {
    private static final int CONSTANT_HUNDRED = 100;
    private final ReentrantLock lock;
    private PriorityQueue&lt;ComparableQueueElement&gt; queue;

    public DynamicPriorityQueue() {
        this(null);
    }

    public DynamicPriorityQueue(Comparator&lt;ComparableQueueElement&gt; comparator) {
        this.lock = new ReentrantLock();
        if (comparator != null) {
            this.queue = new PriorityQueue&lt;ComparableQueueElement&gt;(CONSTANT_HUNDRED, comparator);
        } else {
            this.queue = ew PriorityQueue&lt;ComparableQueueElement&gt;(CONSTANT_HUNDRED);
        }
    }

    public void setFetchByCustomPriority(Comparator&lt;ComparableQueueElement&gt; comparator) {
        // Just replace the existing queue
        PriorityQueue&lt;ComparableQueueElement&gt; newQueue = comparator == null ? new PriorityQueue(queue.size()) : new PriorityQueue(queue.size(), comparator);
        ComparableQueueElement element = queue.poll();
        while(element != null){
            newQueue.push(element); 
            element = queue.poll();
        }
        queue = newQueue;
    }

    public void push(ComparableQueueElement t) throws InterruptedException, TimedOutException {
        if (this.lock.tryLock(CONSTANT_HUNDRED, TimeUnit.MILLISECONDS)) {
            try {
                this.queue.offer(t);
            } finally {
                this.lock.unlock();
            }
        } else {
            throw new TimedOutException();
        }
    }

    public ComparableQueueElement peek() {
        return this.queue.peek();
    }

    public ComparableQueueElement pop() throws InterruptedException, TimedOutException {
        ComparableQueueElement returnElement = null;
        if (this.lock.tryLock(CONSTANT_HUNDRED, TimeUnit.MILLISECONDS)) {
            try {
                return this.queue.pop();
            } finally {
                this.lock.unlock();
            }
        }
        throw new TimedOutException();
    }
}