DelayQueue is a blocking and unbounded queue meaning it supports blocking add and remove operations when queue is full or empty respectively. It can’t contain null values. For other queue and blocking queue characteristics and examples, see Java Queue examples
I’ll show how to use DelayQueue with an example. The example uses DelayQueue to start a chat window after user spends certain time on a web page. Time spent on a page and switch to the new page are simulated using random number of milliseconds as delay between page switches. The example contains delay class, delay object producer and consumer and manger class.
Delay object producer creates and posts a delay object to the delay queue each time there is a page change and delay object consumer processes the delay object and starts the chat.
The class whose instances are used as delay objects to be added to the DelayQueue needs to implement Delayed interface. Delayed interface defines getDelay() method which returns remaining delay time or zero or negative number to indicate that the delay has expired.
In the following example, delay class’s constructor takes start time and delay as arguments and the method getDelay checks if the specified delay has expired or not and returns appropriate value to indicate the expiry. The delay queue uses this method to determine whether a delay element is ready for consumption or not.
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class ChatTask implements Delayed{
private int delayDuration;
private long startTime;
private int currentPage;
public ChatTask(long startTime, int delayDuration, int currentPage) {
this.startTime = startTime;
this.delayDuration = delayDuration;
this.currentPage = currentPage;
}
@Override
public int compareTo(Delayed delayObj) {
if(this.getDelay(null) > delayObj.getDelay(null)) {
return 1;
}
return -1;
}
@Override
public long getDelay(TimeUnit timeUnit) {
if(System.currentTimeMillis() - startTime > delayDuration) {
return 1;
}else {
return 0;
}
}
public int getCurrentPage() {
return currentPage;
}
public int getDelayDuration() {
return delayDuration;
}
}
Delay element producer instantiate delay object and add it to DelayQueue.
import java.util.concurrent.DelayQueue;
public class ChatTaskProducer {
private DelayQueue<ChatTask> chatQueue;
public ChatTaskProducer(DelayQueue<ChatTask> chatQueue) {
this.chatQueue = chatQueue;
}
public void produceChatTask(int delay, int currentPage) {
ChatTask ct = new ChatTask(System.currentTimeMillis(),
delay, currentPage);
chatQueue.add(ct);
System.out.println("added new task, page "+currentPage
+" delay "+delay);
}
}
Consumer of delay element calls take() operation on the delay queue to obtain the expired delay element and process it.
import java.util.concurrent.DelayQueue;
public class ChatTaskConsumer {
private DelayQueue<ChatTask> chatQueue;
private int currentPage;
public ChatTaskConsumer(DelayQueue<ChatTask> chatQueue) {
this.chatQueue = chatQueue;
}
public void startChatTaskConsumer() {
new Thread( new Runnable() {
@Override
public void run() {
//take delayed tasks from the queue and process
processChatTask();
}
}).start();
}
public void processChatTask() {
try {
while(currentPage < 15) {
System.out.println("waiting for task");
ChatTask ct = chatQueue.take();
System.out.println("processing task page "+ct.getCurrentPage()
+" delay "+ct.getDelayDuration());
//if user is on the same after the delay start chat window
if(ct.getCurrentPage() == currentPage) {
initiateChat(ct );
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void initiateChat(ChatTask ct ) {
System.out.println("hello, here to help you on page "
+ct.getCurrentPage());
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
}
import java.util.Random;
import java.util.concurrent.DelayQueue;
public class ChatTaskManger {
private int currentPage;
public static void main(String[] args) {
ChatTaskManger taskManger = new ChatTaskManger();
taskManger.initiateChat();
}
public void initiateChat() {
DelayQueue<ChatTask> chatQueue = new DelayQueue<ChatTask>();
//start consumer
ChatTaskConsumer consumer = new ChatTaskConsumer(chatQueue);
consumer.startChatTaskConsumer();
//instantiate producer
ChatTaskProducer producer = new ChatTaskProducer(chatQueue);
//limit number of elements being sent to queue
while(currentPage < 15) {
//simulate user clicking next page
//after spending some time on current page
waitForPageChange();
currentPage++;
System.out.println("user on page "+currentPage);
//produce chat task delayed element and add it to queue
producer.produceChatTask(getWaitTime(), currentPage);
consumer.setCurrentPage(currentPage);
}
}
public void waitForPageChange() {
try {
Thread.sleep(getWaitTime()*3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int getWaitTime() {
Random random = new Random();
int rval = random.nextInt((10 - 1) + 1) + 1;
return rval*100;
}
}
Output:
waiting for task
user on page 1
added new task, page 1 delay 1000
processing task page 1 delay 1000
hello, here to help you on page 1
waiting for task
user on page 2
added new task, page 2 delay 500
processing task page 2 delay 500
hello, here to help you on page 2
waiting for task
user on page 3…