Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do i set up a DelayQueue's Delay

I'm just starting out coding in java i'm in struggling with setting up a DelayQueue,

I wanted to have it so,

DelayQueue queue = new DelayQueue();

If (counter > 0){
queue.offer(Integer, *A custom delay*)
} Else {
queue.offer(Integer, *A different custom delay*)
}

I'm just trying to learn all the basics and ive read over the API and cant seem to grasp it.

Thanks in advance

like image 376
Pstie Avatar asked Dec 05 '22 06:12

Pstie


2 Answers

this implementation of Delayed is good because:

  • implementation of compareTo() does not do any class casting, eliminatig the possibility of throwing a ClassCastException
  • implementation of compareTo() uses Math.min and Math.max functions before casting to int in order to properly prevent overflow errors
  • implementation of getDelay() properly converts the units and actually returns the time remaining

TestDelay class implements Delayed:

import org.jetbrains.annotations.NotNull;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class TestDelay implements Delayed
{
    public final Long delayMillis;
    public final Long expireTimeMillis;

    public TestDelay(Long delayMillis)
    {
        this.delayMillis = delayMillis;
        this.expireTimeMillis = System.currentTimeMillis()+delayMillis;
    }

    @Override
    public final int compareTo(@NotNull Delayed o)
    {
        long diffMillis = getDelay(TimeUnit.MILLISECONDS)-o.getDelay(TimeUnit.MILLISECONDS);
        diffMillis = Math.min(diffMillis,1);
        diffMillis = Math.max(diffMillis,-1);
        return (int) diffMillis;
    }

    @Override
    public final long getDelay(@NotNull TimeUnit unit)
    {
        long delayMillis = expireTimeMillis-System.currentTimeMillis();
        return unit.convert(delayMillis,TimeUnit.MILLISECONDS);
    }
}

JUnit unit test showing an example of using the TestDelay class:

import org.junit.Test;

import java.util.concurrent.DelayQueue;

public class DelayQueueTest
{
    @Test
    public final void generalTest() throws InterruptedException
    {
        DelayQueue<TestDelay> q = new DelayQueue<>();
        q.put(new TestDelay(500L));
        q.put(new TestDelay(2000L));
        q.put(new TestDelay(1000L));
        q.put(new TestDelay(10L));
        q.put(new TestDelay(3000L));
        while (!q.isEmpty())
        {
            System.out.println(q.take().delayMillis);
        }
    }
}

output of DelayQueueTest:

unit test output

like image 127
Eric Avatar answered Jan 12 '23 14:01

Eric


import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class DelayQueueExample {

    public static void main(String[] args) {

        BlockingQueue<DelayedElement> blockingQueue = new DelayQueue<DelayedElement>();

        try {
            blockingQueue
                    .put(new DelayedElement(4000, "Message with delay 4s"));
            blockingQueue
                    .put(new DelayedElement(2000, "Message with delay 2s"));
            blockingQueue
                    .put(new DelayedElement(9000, "Message with delay 9s"));
        } catch (InterruptedException ie) {
        }

        while (!blockingQueue.isEmpty()) {
            try {
                System.out.println(">>" + blockingQueue.take());
            } catch (InterruptedException ie) {
            }

        }

    }
}

class DelayedElement implements Delayed {

    private long duration = 0;
    private String message;

    public DelayedElement(long duration, String name) {
        this.duration = System.currentTimeMillis() + duration;
        this.message = name;
    }

    @Override
    public int compareTo(Delayed o) {
        return (int) (this.duration - ((DelayedElement) o).getDuration());
    }

    @Override
    /*
     * Expiration occurs when an element's getDelay(TimeUnit unit) method
     * returns a value less than or equal to zero.
     */
    public long getDelay(TimeUnit unit) {
        long diff = duration - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
    }

    public long getDuration() {
        return duration;
    }

    public void setDuration(long duration) {
        this.duration = duration;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return "DelayedElement [duration=" + duration + ", message=" + message
                + "]";
    }

}
like image 40
Sandeep Bhardwaj Avatar answered Jan 12 '23 16:01

Sandeep Bhardwaj