Контейнер ожидаемых объектов Java

#java

#java

Вопрос:

Существуют ли существующие фреймворки, реализующие следующий подход?

 public class WaitableContainer<T> {
  private T object;
  public <T> peekAwait() {...} // returns object if object !=null or makes the caller thread sleep until object != null
  public actuate(T object) {
    this.object = object; // here all sleeping threads must awake and receive the new object
  }
}
  

Нужна какая-то объектная оболочка, которая заставит вызывающий поток отключаться до тех пор, пока другой поток не установит объект.

Комментарии:

1. Я думаю, что интерфейс BlockingQueue может быть полезен (по крайней мере, для первого метода). Я действительно не понимаю, что должен делать actuate

2. также вы можете попробовать java Future

3. Похоже, что это работа для CyclicBarrier

4. При проектировании предполагается, что какой-то поток может пропустить объект, если он еще не вызывался peekAwait . Это правда? Готовы ли вы к сценарию, когда вы actuate создаете объект, но некому его просмотреть, и он исчезает?

Ответ №1:

Это звучит как завершаемое будущее.

 // container.actuate(o); becomes
future.complete(o);

// container.peekAwait(); becomes
future.get();
  

Если вы не можете использовать Java 8, FutureTask — достойный выбор для обхода, но вместо явной настройки вы предоставляете вызываемый объект, который возвращает значение, которое вы хотите установить.

 final FutureTask<Object> lazyLoadedData = new FutureTask<>(() -> expensiveIO());

...

if (!lazyLoadedData.isDone()) {
    synchronized(lazyLoadedData) {
        if (!lazyLoadedData.isDone()) {
            // run() does the computation and sets the data
            // essentially, lazyLoadedData.set(expensiveIO())
            lazyLoadedData.run();
        }
    }
}
// Data is available
lazyLoadedData.get();
  

Если вы планируете, чтобы это делал ExecutorService, он уже возвращает Future;

 final FutureTask<Object> future = executorService.submit(() -> expensiveIO());

// Now you just need to call get()
future.get();