views:

503

answers:

2

Essentially what I want is a BlockingQueue of size=1. I have a "listener" thread that simply waits, blocking until an object is put into the queue, and then retrieves it--and a "producer" thread that actually puts the object into the queue.

I can implement this with some synchronized blocks and a BlockingQueue implementation, but that seems like overkill. Is there a better, simpler way to do what I want?

Example interface:

public interface Wait<T> {
  /**
   * If "put" has never been called on this object, then this method will
   * block and wait until it has. Once "put" has been called with some T, this
   * method will return that T immediately.
   */
  public T get() throws InterruptedException;

  /**
   * @param object The object to return to callers of get(). If called more
   * than once, will throw an {@link IllegalStateException}.
   */
  public void put(T object);
}
+2  A: 

You mean something like SynchronousQueue? Another useful class is Exchanger

ddimitrov
No, not quite. I've added a more specific example of exactly what I'm looking for.
Ross
A: 

I found code for a class called "ObjectLatch" here: http://forums.sun.com/thread.jspa?threadID=5321141

package jfco.progs;

import java.util.concurrent.CountDownLatch;

/**
 * <H1>A Blocking Object Latch</H1> This class implements a blocking object
 * latch, that acts as a synchronizer between a producer of an object and it's
 * consumer(s).
 * <p>
 * An object is set with <code>set()</code>only ONCE. Further attempts to set
 * the object are just ignored.<br>
 * <p>
 * Consumers request the object with <code>get()</code>. If the object is not
 * already set, consumers are blocked waiting until the object is available or <br>
 * until an interrupt (InteruptedException) terminates the wait.
 * <p>
 * The latch can be tested for object availability with isAvailable(), which
 * answers true if the object has already been set. <br>
 */
public class ObjectLatch<R> {

    /** The object. */
    private R object = null;

    /** The latch counter created and set to 1. */
    private final CountDownLatch latch = new CountDownLatch(1);

    /**
     * Checks if the object is already available (has been already set).
     * 
     * @return true, if the object is already available (has been already set)
     */
    public boolean isAvailable() {
        return latch.getCount() == 0;
    }

    /**
     * Sets the object if it is not already set. Otherwise ignore this request.
     * 
     * @param object
     *            the object
     */
    public synchronized void set(R object) {
        if (!isAvailable()) {
            this.object = object;
            latch.countDown();
        }
    }

    /**
     * Get the object if it is already available (has already been set).
     * <p>
     * If it is not available, wait until it is or until an interrupt
     * (InterruptedException) terminates the wait.
     * 
     * @return the object if it is already available (has already been set)
     * 
     * @throws InterruptedException
     */
    public R get() throws InterruptedException {
        latch.await();
        synchronized (this) {
            return object;
        }
    }
}
Ross