I am trying to have a ReentrantLock with another way to determinate which thread will have the lock in the waiting queue. ReentrantLock implementation manages a Fair/Unfair policy, that's not what I want.
I would like to give a priority when I call the .lock() method, and this priority will determinate the order of current thread in the waiting threads queue.
I wrote a class, based on a PriorityBlockingQueue, and I'd like your opinion.
import java.util.Date;
import java.util.concurrent.PriorityBlockingQueue;
/**
* Class to lock a resource.
* When multiple threads are waiting for the resource to be unlocked, the one with the greatest priority will have the resource.
* When two threads have the same priority, the first added thread will lock the resource.
*
*/
public class PrioritizedLock {
private PriorityBlockingQueue<PrioritizedThread> waitingQueue = new PriorityBlockingQueue<PrioritizedThread>();
private volatile PrioritizedThread activeThread;
private volatile Object syncStartNext = new Object();
private volatile boolean shutdown = false;
public PrioritizedLock() {
startQueueWatcher();
}
/**
* Starts a queue watcher, which takes PrioritizedThread from the PriorityBlockingQueue and notify them to wake them up.
*/
private void startQueueWatcher() {
new Thread(new Runnable() {
@Override
public void run() {
while (!shutdown) {
/*
* Wait until a PrioritizedThread is added to the PriorityBlockingQueue
*/
while (activeThread == null) {
try {
activeThread = waitingQueue.take();
} catch (InterruptedException e1) {
//
}
}
/*
* Notify the thread to wake up (now it has locked the resource)
*/
synchronized (activeThread) {
activeThread.notify();
}
/*
* Wait until the resource has been released from the active thread
*/
while (activeThread != null) {
synchronized (syncStartNext) {
try {
syncStartNext.wait();
} catch (InterruptedException e) {
//
}
}
}
}
}
}).start();
}
/**
* Waits until the thread is woken up by the Queue Watcher thread
* @param thread
*/
private void wait(PrioritizedThread thread) {
synchronized (thread) {
while (activeThread != thread) {
try {
thread.wait();
} catch (InterruptedException e) {
//
}
}
}
}
static class PrioritizedThread implements Comparable<PrioritizedThread> {
Thread thread;
int priority;
Date date = new Date();
public PrioritizedThread(Thread aThread, int aPriority) {
thread = aThread;
priority = aPriority;
}
@Override
public int compareTo(PrioritizedThread other) {
int diffPriorities = this.priority - other.priority;
if (diffPriorities == 0) {
return date.compareTo(other.date);
}
return diffPriorities;
}
}
/**
* Waits until the resource is locked by the current thread
* @param priority Priority of the lock, the less has the greatest priority
*/
public void lock(int priority) {
PrioritizedThread prioritizedThread = new PrioritizedThread(Thread.currentThread(), priority);
waitingQueue.add(prioritizedThread);
wait(prioritizedThread);
}
/**
* Unlock the resource
*/
public void unlock() {
activeThread = null;
synchronized (syncStartNext) {
syncStartNext.notify();
}
}
/**
* Trigger a shutdown of the lock,
*/
public void shutdown() {
shutdown = true;
}
}