package chatty.util;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Logger;
/**
* A queue that items can be added to, that are send to the registered action
* listener on a fixed delay (in between each item). The queue is FIFO.
*
* @author tduva
* @param <E> The type of the items
*/
public class DelayedActionQueue<E> {
private static final Logger LOGGER = Logger.getLogger(DelayedActionQueue.class.getName());
private final DelayedActionListener<E> listener;
private final long delay;
private final BlockingQueue<E> q = new LinkedBlockingQueue<>();
/**
* Create a new queue object and start it.
*
* @param <T>
* @param listener
* @param delay
* @return
*/
public static<T> DelayedActionQueue<T> create(DelayedActionListener<T> listener, long delay) {
DelayedActionQueue<T> q = new DelayedActionQueue<>(listener, delay);
q.start();
return q;
}
/**
* Creates a new instance.
*
* @param listener The listener to send the items to (can't be {@code null})
* @param delay The delay between items in milliseconds
*/
private DelayedActionQueue(DelayedActionListener<E> listener, long delay) {
this.listener = listener;
this.delay = delay;
}
/**
* Start a new reader thread. This should only be called once per instance.
*/
private void start() {
new Reader().start();
}
/**
* Adds an item to the queue.
*
* @param item
*/
public void add(E item) {
q.add(item);
}
/**
* Clears all elements from the queue.
*/
public void clear() {
q.clear();
}
/**
* Thread that reads an item (or blocks if none is available) sends it to
* the listener and then waits for the specified delay.
*/
private class Reader extends Thread {
@Override
public void run() {
while (true) {
try {
E item = q.take();
listener.actionPerformed(item);
sleep(delay);
} catch (InterruptedException ex) {
LOGGER.warning("Reader Thread interrupted.");
break;
}
}
}
}
public static interface DelayedActionListener<E> {
public void actionPerformed(E item);
}
}