org.jgroups.util.ConcurrentLinkedBlockingQueue Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
package org.jgroups.util;
import java.util.Collection;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.LockSupport;
/**
* Attempt at writing a fast transfer queue, which is bounded. The take() method blocks until there is an element, but
* the offer() method drops the element and returns if the queue is full (doesn't block). I thought this class would
* be useful in ThreadPoolExecutor, as a replacement for LinkedBlockingQueue, but the perf didn't change. I'll keep it
* for later reference ...
* @author Bela Ban
*/
public class ConcurrentLinkedBlockingQueue extends ConcurrentLinkedQueue implements BlockingQueue {
private static final long serialVersionUID=-8884995454506956809L;
private final int capacity;
private final Lock lock=new ReentrantLock();
private final Condition not_empty=lock.newCondition();
private final AtomicInteger waiting_takers=new AtomicInteger(0);
public ConcurrentLinkedBlockingQueue(int capacity) {
this.capacity=capacity;
}
// The methods below are used by ThreadPoolExecutor ///////////
/**
* Drops elements if capacity has been reached. That's OK for the ThreadPoolExecutor as dropped messages
* will get retransmitted
* @param t
* @return
*/
public boolean offer(T t) {
boolean retval=size() < capacity && super.offer(t);
if(waiting_takers.get() > 0) {
lock.lock();
try {
not_empty.signal();
}
finally {
lock.unlock();
}
}
return retval;
}
public T take() throws InterruptedException {
T retval=null;
for(;;) {
retval=poll();
if(retval != null)
return retval;
while(size() == 0) {
waiting_takers.incrementAndGet();
lock.lockInterruptibly();
try {
not_empty.await();
}
finally {
lock.unlock();
waiting_takers.decrementAndGet();
}
}
}
}
public T poll() {
return super.poll();
}
public T poll(long timeout, TimeUnit unit) throws InterruptedException {
long sleep_time_nanos=TimeUnit.NANOSECONDS.convert(timeout, unit);
long target_time_nanos=System.nanoTime() + sleep_time_nanos;
sleep_time_nanos/=5;
T el=null;
while(System.nanoTime() < target_time_nanos) {
if((el=poll()) != null)
return el;
LockSupport.parkNanos(sleep_time_nanos);
}
return el;
}
public boolean remove(Object o) {
return super.remove(o);
}
public int remainingCapacity() {
return capacity - size();
}
public int drainTo(Collection super T> c) {
int count=0;
if(c == null)
return count;
for(;;) {
T el=poll();
if(el == null)
break;
c.add(el);
count++;
}
return count;
}
/////////////////////////////////////////////////////////////////
public void put(T t) throws InterruptedException {
super.offer(t);
}
public boolean offer(T t, long timeout, TimeUnit unit) throws InterruptedException {
return offer(t);
}
public int drainTo(Collection super T> c, int maxElements) {
return drainTo(c);
}
}