问题
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
回答1:
The DelayQueue
keeps the elements internally until a certain delay has expired. The elements must implement the interface java.util.concurrent.Delayed
.
For example I have created a class DelayedTest
extending Delayed interface. This will implement compareTo and getDelay() method
public class A{
public static void main(String... args){
DelayQueue dq=new DelayQueue();
DeleyedTest ob1=new DeleyedTest(10);
DeleyedTest ob2=new DeleyedTest(5);
DeleyedTest ob3=new DeleyedTest(15);
dq.offer(ob1);
dq.offer(ob2);
dq.offer(ob3);
Iterator itr=dq.iterator();
while(itr.hasNext()){
DeleyedTest dt=(DeleyedTest)itr.next();
System.out.println(dt.deleyTime);
}
}
}
class DeleyedTest implements Delayed{
public long deleyTime=0;
DeleyedTest(long deleyTime){
this.deleyTime=deleyTime;
}
@Override
public int compareTo(Delayed ob) {
if(this.deleyTime<((DeleyedTest)ob).deleyTime){
return -1;
}else if(this.deleyTime>((DeleyedTest)ob).deleyTime){
return 1;
}
return 0;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(deleyTime-System.currentTimeMillis(),TimeUnit.NANOSECONDS);
}
}
Result:
5 10 15
回答2:
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
+ "]";
}
}
回答3:
this implementation of Delayed
is good because:
- implementation of
compareTo()
does not do any class casting, eliminatig the possibility of throwing aClassCastException
- implementation of
compareTo()
usesMath.min
andMath.max
functions before casting toint
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
:
回答4:
Your "custom delay" classes must return the delay from the getDelay(TimeUnit timeUnit)
method specified in the Delayed
interface.
E.g.
public class MyClass implements Delayed {
public long getDelay(TimeUnit timeUnit) {
long delay = calculateDelaySomehow();
return delay;
}
}
Note that you also need to provide an implementation for compareTo()
.
来源:https://stackoverflow.com/questions/23219801/how-do-i-set-up-a-delayqueues-delay