这个“容器设计模式”应该叫什么名字?

3
在创建我的应用程序架构时,我遇到了需要描述的一个结构。
我非常确定有一个已知的设计模式具有相同的功能,因为我认为开发它的问题确实很普遍。
我编写了自己的实现,但我总是尝试使用“内置语言”模式的实现,因此,请帮助我命名此结构。
这个想法接近于读者-写者模式。我们有一个“容器”,可以通过键()添加对象。我们也可以通过键获取这些对象,并从容器中删除它们。
因此,实现的类应该有两个方法:
void putObject(Key key, Object object);
Object getObject(Key key); // remove <Key,Object> from container.

以下是最有趣的部分。 这个容器应该在多线程环境下工作,如下所示
  1. 如果没有与键相关联的对象,在调用get(Key key)方法时,调用线程应等待此容器中的对象。
  2. 当另一个线程调用putObject(Key key,Object object)方法时,它应检查是否有一些线程正等待此对象,如果是,则发出信号并唤醒等待的线程。
我认为这是一个常见的结构,它有“官方”名称吗?
这是我对该模式的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
实际上,您正在谈论一种在多线程中具有棘手行为的Map(某种程度上,这种行为似乎类似于某种队列逻辑)。据我所知,在任何Java集合的实现中,都没有这样的行为。无论如何,您都必须修改库的实现。 - sphinks
你是在说BlockingQueue吗? - Yaroslav Rudykh
@YaroslavRudykh 我想这很接近了,但没有键对象关系。在队列中,我们按顺序读取对象,而不是按键读取。 - sphinks
好的,对我来说现在它被称为“阻塞并发映射”。 - Crabonog
您是否也需要编写线程等待,直到其他线程读取该元素? - fps
显示剩余2条评论
2个回答

2
我会使用类似于 `

` 的东西。

ConcurrentMap<K,BlockingQue<V>>. 

使用Map的并发方法添加键值对。从队列中获取值。可以使用ArrayBlockingQueue(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));
    }
}

好的设计。谢谢! - Crabonog

1
看到你的设计,对我来说你所描述的是类似于并发对象池。它使用一组已初始化的对象,保持准备好使用。池的客户端将从池中请求一个对象,并对返回的对象执行操作。唯一真正的区别在于你是根据自己的标准获取对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接