mirror of https://github.com/mchr3k/org.intrace
165 lines
5.9 KiB
Java
165 lines
5.9 KiB
Java
package org.intracetest.agent;
|
|
|
|
|
|
import java.util.List;
|
|
import java.util.ArrayList;
|
|
import java.util.concurrent.Delayed;
|
|
import java.util.concurrent.DelayQueue;
|
|
import java.util.concurrent.TimeUnit;
|
|
import org.junit.Test;
|
|
import org.junit.Before;
|
|
import static org.junit.Assert.assertTrue;
|
|
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
|
|
|
|
|
|
import java.util.concurrent.BlockingQueue;
|
|
import java.util.concurrent.DelayQueue;
|
|
|
|
import org.intrace.output.trace.TraceHandler;
|
|
import static org.junit.Assert.assertEquals;
|
|
|
|
/** This is a 'proof of concept' test that demonstrates how to use a DelayQueue to emit
|
|
* data in batches, instead of individual queue items. Only jdk code and test code is exercised here.
|
|
*
|
|
* This test sticks 9 items into a DelayQueue. These items comes out in 3 batches.
|
|
* The delays (in milliseconds) between the batches are defined in the offsetA, offsetB, and offsetC variables.
|
|
*/
|
|
public class DelayQueueProofOfConceptTest
|
|
{
|
|
public static final int POISON_PILL = 3;
|
|
private static long offsetA = 53L;
|
|
private static long offsetB = 109L;
|
|
private static long offsetC = 150L;
|
|
private static long baseline = 0;
|
|
BlockingQueue<Pizza> pizzaQueue = new DelayQueue<Pizza>();
|
|
PizzaEaterRunnable pizzaEater = new PizzaEaterRunnable(pizzaQueue);
|
|
List<Long> expectedArrivalTimestamps = new ArrayList<Long>();
|
|
@Before
|
|
public void setup() throws java.lang.InterruptedException {
|
|
baseline = System.currentTimeMillis();
|
|
|
|
/**
|
|
* B A T C H # 1
|
|
*/
|
|
pizzaQueue.put( createTypeOne(baseline) ); expectedArrivalTimestamps.add( new Long(baseline+offsetA) );
|
|
pizzaQueue.put( createTypeOne(baseline) ); expectedArrivalTimestamps.add( new Long(baseline+offsetA) );
|
|
pizzaQueue.put( createTypeOne(baseline) ); expectedArrivalTimestamps.add( new Long(baseline+offsetA) );
|
|
pizzaQueue.put( createTypeOne(baseline) ); expectedArrivalTimestamps.add( new Long(baseline+offsetA) );
|
|
pizzaQueue.put( createTypeOne(baseline) ); expectedArrivalTimestamps.add( new Long(baseline+offsetA) );
|
|
/**
|
|
* B A T C H # 2
|
|
*/
|
|
pizzaQueue.put( createTypeTwo(baseline) ); expectedArrivalTimestamps.add( new Long(baseline+offsetB) );
|
|
pizzaQueue.put( createTypeTwo(baseline) ); expectedArrivalTimestamps.add( new Long(baseline+offsetB) );
|
|
pizzaQueue.put( createTypeTwo(baseline) ); expectedArrivalTimestamps.add( new Long(baseline+offsetB) );
|
|
/**
|
|
* B A T C H # 3
|
|
*/
|
|
|
|
pizzaQueue.put( createTypeThree(baseline) ); expectedArrivalTimestamps.add( new Long(baseline+offsetC) );
|
|
}
|
|
private Pizza createTypeOne(long baseline) {
|
|
Pizza newPizza = new Pizza( baseline + offsetA, 1 );
|
|
return newPizza;
|
|
}
|
|
|
|
private Pizza createTypeTwo(long baseline) {
|
|
Pizza newPizza = new Pizza( baseline + offsetB, 2 );
|
|
return newPizza;
|
|
}
|
|
private Pizza createTypeThree(long baseline) {
|
|
Pizza newPizza = new Pizza( baseline + offsetC, POISON_PILL );
|
|
return newPizza;
|
|
}
|
|
@Test
|
|
public void testDelayQueueBurst() {
|
|
try {
|
|
PizzaEaterRunnable eater = new PizzaEaterRunnable(pizzaQueue);//queue was filled in setup method
|
|
Thread t = new Thread(eater);
|
|
t.start();
|
|
//Time will elapse as DelayQueue emits
|
|
//a three bursts of pizzas from the queue, 1 second between each burst.
|
|
//The thread will finish when a 'poison pill' is detected by the thread.
|
|
t.join();
|
|
boolean compare = eater.arrivalTimestamps.equals(expectedArrivalTimestamps);
|
|
String actual = eater.arrivalTimestamps.toString();
|
|
String expected = expectedArrivalTimestamps.toString();
|
|
assertTrue("did not get expected arrival times. Expected [" + expected + "] Actual [" + actual + "]",compare);
|
|
|
|
} catch (InterruptedException ie) {
|
|
ie.printStackTrace();
|
|
}
|
|
}
|
|
|
|
public static class Pizza implements Delayed {
|
|
|
|
private long departureTimestampMillis = 0L;
|
|
private int type = 0;
|
|
public Pizza(long val, int type) {
|
|
this.departureTimestampMillis = val;
|
|
this.type = type;
|
|
System.out.println("New Pizza [" + this.toString() + "]");
|
|
}
|
|
public String toString() {
|
|
return "Pizza {departureTimestampMillis=" + this.departureTimestampMillis + ",type=" + this.type + "}";
|
|
}
|
|
public int getType() {
|
|
return this.type;
|
|
}
|
|
@Override
|
|
public long getDelay(TimeUnit unit) {
|
|
long ts = System.currentTimeMillis();
|
|
//System.out.println("current [" + ts + "] " + this.toString()) ;
|
|
return this.departureTimestampMillis - ts;
|
|
}
|
|
|
|
@Override
|
|
public int compareTo(Delayed o) {
|
|
long rc = this.getDelay( TimeUnit.MILLISECONDS ) - o.getDelay( TimeUnit.MILLISECONDS );
|
|
return (int)rc;
|
|
}
|
|
}
|
|
class PizzaEaterRunnable implements Runnable {
|
|
private static final int batchSize = 1000000;//Only concerned with huge/horrible events, otherwise monitoring is required to tune batch size.
|
|
public List<Long> arrivalTimestamps = new ArrayList<Long>();
|
|
BlockingQueue<Pizza> pizzaQueue;
|
|
public volatile boolean stopRequested = false;
|
|
public PizzaEaterRunnable(BlockingQueue<Pizza> val) {
|
|
this.pizzaQueue = val;
|
|
}
|
|
private void eatMany(List<Pizza> manyPizzas) {
|
|
for(Pizza pizza : manyPizzas)
|
|
eat(pizza);
|
|
}
|
|
private void eat(Pizza pizza) {
|
|
arrivalTimestamps.add( new Long(System.currentTimeMillis()) );
|
|
if (pizza.getType() == DelayQueueProofOfConceptTest.POISON_PILL) {
|
|
this.stopRequested = true;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
List<Pizza> manyPizzas = new ArrayList<Pizza>();
|
|
while (!stopRequested) {
|
|
try {
|
|
//System.out.println(Thread.currentThread().getName() + " eating up bread ");
|
|
Pizza pizza = pizzaQueue.poll(100, TimeUnit.MILLISECONDS);
|
|
if (pizza !=null) {
|
|
manyPizzas.add(pizza);
|
|
pizzaQueue.drainTo(manyPizzas,batchSize);
|
|
eatMany(manyPizzas);
|
|
manyPizzas.clear();
|
|
}
|
|
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|