I agree with Andrew Duffy's remark that implementing such a time-constrained system in java may be a mistake. Regardless, assuming you're married to the JVM, and you don't expect this queue to be running full (ie, the consumer can handle the load), I think you might be best served by a custom implementation, similar to an ArrayBlockingQueue but trimmed down/optimized for the single producer/consumer scenario. In particular, I'm liking the notion of spinning on the producer-side to wait for space, rather than blocking.
I referred to the java.concurrent sources for guidance, and drafted up this algorithm...
It looks pretty good to me, but it's entirely untested and may not be any faster in practice (probably not revolutionary, but I did crank it out myself :-). I had fun with it, anyway... Can you find a flaw?
Pseudocode:
private final ReentrantLock takeLock = new ReentrantLock();
private final Condition notEmpty = takeLock.newCondition();
private final E[] buffer;
private int head = 0
private int tail = 0;
public void put(E e) {
if (e == null) throw NullPointerException();
while (buffer[tail] != null) {
// spin, wait for space... hurry up, consumer!
// open Q: would a tight/empty loop be superior here?
Thread.sleep(1);
}
buffer[tail] = e;
tail = (tail + 1) % buffer.length;
if (count.getAndIncrement() == 0) {
sync(takeLock) { // this is pseudocode -- should be lock/try/finally/unlock
notEmpty.signal();
}
}
}
public E take() {
sync(takeLock) {
while (count.get() == 0) notEmpty.await();
}
E item = buffer[head];
buffer[head] = null;
count.decrement();
head = (head + 1) % buffer.length;
return item;
}