@@ -45,10 +45,12 @@ public class Consumer extends ProducerConsumerBase implements Runnable {
4545 private final long timeLimit ;
4646 private final CountDownLatch latch = new CountDownLatch (1 );
4747 private final Map <String , String > consumerTagBranchMap = Collections .synchronizedMap (new HashMap <String , String >());
48+ private final ConsumerLatency consumerLatency ;
4849
4950 public Consumer (Channel channel , String id ,
5051 List <String > queueNames , int txSize , boolean autoAck ,
51- int multiAckEvery , Stats stats , float rateLimit , int msgLimit , int timeLimit ) {
52+ int multiAckEvery , Stats stats , float rateLimit , int msgLimit , int timeLimit ,
53+ int consumerLatencyInMicroSeconds ) {
5254
5355 this .channel = channel ;
5456 this .id = id ;
@@ -60,6 +62,13 @@ public Consumer(Channel channel, String id,
6062 this .stats = stats ;
6163 this .msgLimit = msgLimit ;
6264 this .timeLimit = 1000L * timeLimit ;
65+ if (consumerLatencyInMicroSeconds <= 0 ) {
66+ this .consumerLatency = new NoWaitConsumerLatency ();
67+ } else if (consumerLatencyInMicroSeconds >= 1000 ) {
68+ this .consumerLatency = new ThreadSleepConsumerLatency (consumerLatencyInMicroSeconds / 1000 );
69+ } else {
70+ this .consumerLatency = new BusyWaitConsumerLatency (consumerLatencyInMicroSeconds * 1000 );
71+ }
6372 }
6473
6574 public void run () {
@@ -121,7 +130,10 @@ public void handleDelivery(String consumerTag, Envelope envelope, BasicPropertie
121130 now = System .currentTimeMillis ();
122131
123132 stats .handleRecv (id .equals (envelope .getRoutingKey ()) ? (nano - msgNano ) : 0L );
124- delay (now );
133+ if (rateLimit > 0.0f ) {
134+ delay (now );
135+ }
136+ consumerLatency .simulateLatency ();
125137 }
126138 if (msgLimit != 0 && msgCount >= msgLimit ) { // NB: not quite the inverse of above
127139 latch .countDown ();
@@ -145,4 +157,53 @@ public void handleCancel(String consumerTag) throws IOException {
145157 }
146158 }
147159 }
160+
161+ private interface ConsumerLatency {
162+
163+ void simulateLatency ();
164+
165+ }
166+
167+ private static class NoWaitConsumerLatency implements ConsumerLatency {
168+
169+ @ Override
170+ public void simulateLatency () {
171+ // NO OP
172+ }
173+
174+ }
175+
176+ private static class ThreadSleepConsumerLatency implements ConsumerLatency {
177+
178+ private final int waitTime ;
179+
180+ private ThreadSleepConsumerLatency (int waitTime ) {
181+ this .waitTime = waitTime ;
182+ }
183+
184+ @ Override
185+ public void simulateLatency () {
186+ try {
187+ Thread .sleep (waitTime );
188+ } catch (InterruptedException e ) {
189+ throw new RuntimeException ("Exception while simulating latency" , e );
190+ }
191+ }
192+ }
193+
194+ // from https://stackoverflow.com/a/11499351
195+ private static class BusyWaitConsumerLatency implements ConsumerLatency {
196+
197+ private final long delay ;
198+
199+ private BusyWaitConsumerLatency (long delay ) {
200+ this .delay = delay ;
201+ }
202+
203+ @ Override
204+ public void simulateLatency () {
205+ long start = System .nanoTime ();
206+ while (System .nanoTime () - start < delay );
207+ }
208+ }
148209}
0 commit comments