3

При создании моего приложения. архитектуры, я столкнулся с необходимостью для одной структуры, которая будет описана ниже.Как называется этот шаблон дизайна контейнера?

Я уверен, что есть хорошо известный шаблон дизайна с одинаковой функциональностью, потому что я думаю, что проблема, для которой я ее развиваю, очень распространена.

Я пишу свою собственную реализацию этого, но я всегда стараюсь использовать «на языке» реализации шаблонов, поэтому - пожалуйста, помогите мне назвать эту конструкцию.

Идея близка к шаблону считывающего устройства. У нас есть «контейнер», в который мы можем добавить объекты ключом(). А также мы можем получить эти объекты с помощью ключей, удалив их из контейнера.

Таким образом, реализованная класс должен иметь два метода:

void putObject(Key key, Object object); 
Object getObject(Key key); // remove <Key,Object> from container. 

Следующая является наиболее интересным. Этого контейнер должен работать в многопоточной среде следующего:

  1. Если нет объекта, связанного с ключом, при вызове Получа (Key ключа) поток вызывающего абонента должен ЖДАТЬ объект в этом контейнер.
  2. Когда другой поток будет вызывать putObject (Key ключ, объект Object) метода, который он должен проверить, есть ли какой-то поток, что ждать именно для этого объекта, и если это - то сигнала и просыпается нить, что ждет.

Я думаю, что это общая структура, имеет ли это «официальное» имя?

My Java реализация этой модели:

private static interface BlackBox { 

     public void addObject(IdObject object); 

     public IdObject getObject(ObjectId id); 

    } 

    private static class BlackBoxImpl implements BlackBox { 

     private final Lock conditionLock = new ReentrantLock(); 
     private final Map<ObjectId, IdObject> savedObjects; 
     private final Map<ObjectId, Condition> waitingConditions; 

     public BlackBoxImpl() { 
      this.savedObjects = new ConcurrentHashMap<ObjectId, IdObject>(20); 
      this.waitingConditions = new ConcurrentHashMap<ObjectId, Condition>(20); 
     } 

     @Override 
     public void addObject(IdObject object) { 
      savedObjects.put(object.getId(), object); 
      if (waitingConditions.containsKey(object.getId())) { 
       Condition waitCondition = waitingConditions.get(object.getId()); 
       conditionLock.lock(); 
       waitCondition.signal(); 
       conditionLock.unlock(); 
      } 
     } 

     @Override 
     public IdObject getObject(ObjectId id) { 
      if (savedObjects.containsKey(id)) { 
       return savedObjects.get(id); 
      } else { 
       conditionLock.lock(); 
       Condition waitCondition = conditionLock.newCondition(); 
       waitingConditions.put(id, waitCondition); 
       waitCondition.awaitUninterruptibly(); 
       conditionLock.unlock(); 
       return savedObjects.get(id); 
      } 
     } 

    } 

    private static interface IdObject { 

     public ObjectId getId(); 

    } 

    private static class IdObjectImpl implements IdObject { 

     protected final ObjectId id; 

     public IdObjectImpl(ObjectId id) { 
      this.id = id; 
     } 

     @Override 
     public ObjectId getId() { 
      return id; 
     } 

    } 

    private static interface ObjectId { 

    } 

    private static class ObjectIdImpl implements ObjectId { 

    } 
+1

На самом деле, вы говорите о какой-то карте с сложным поведением в многопоточности (как-то такое поведение похоже на какую-то логику очереди). Насколько я знаю, такого поведения нет в любой реализации Java-коллекции. В любом случае вам необходимо изменить реализацию библиотеки. – sphinks

+0

Вы говорили о BlockingQueue? –

+0

@ YaroslavRudykh Я полагаю, что это очень близко, но нет отношения Key-Object. В очереди мы читаем объект по заказу, а не по ключу. – sphinks

ответ

2

я бы, вероятно, использовать что-то вроде

ConcurrentMap<K,BlockingQue<V>>. 

Используйте параллельные методы карте, чтобы добавить пару. Возьмите из своей очереди значение. Используйте ArrayBlockingQue (1).

Нечто подобное возможно:

static class MultiQueue<K, V> { 

    // The base structure. 
    final ConcurrentMap<K, BlockingQueue<V>> queues = new ConcurrentHashMap<>(); 

    /** 
    * Put an item in the structure. 
    * 
    * The entry in the map will be created if no entry is currently there. 
    * 
    * The value will then be posted to the queue. 
    */ 
    public void put(K k, V v) throws InterruptedException { 
     // Make it if not present. 
     ensurePresence(k).put(v); 
    } 

    /** 
    * Get an item from the structure. 
    * 
    * The entry in the map will be created if no entry is currently there. 
    * 
    * The value will then be taken from the queue. 
    */ 
    public void get(K k) throws InterruptedException { 
     // Make it if not present - and wait for it. 
     ensurePresence(k).take(); 
    } 

    private BlockingQueue<V> ensurePresence(K k) { 
     // Make it if not present. 
     return queues.computeIfAbsent(k, v -> new ArrayBlockingQueue(1)); 
    } 
} 
+0

Nice degisn. Спасибо! – Crabonog

1

Глядя на ваш дизайн, мне то, что вы описываете

У нас есть «контейнер», в котором можно добавлять объекты с помощью ключа() , А также мы можем получить эти объекты с помощью ключей, удалив их из контейнера. Этот контейнер должен работать в многопоточной среде

близка к Параллельное Object pool. Он использует набор инициализированных объектов, готовых к использованию. Клиент пула будет запрашивать объект из пула и выполнять операции с возвращенным объектом.

Единственная реальная разница, которую я вижу, заключается в том, что вы получаете объекты, основанные на ваших собственных критериях.

Смежные вопросы