简体   繁体   English

ConcurrentHashMap 等待键可能吗?

[英]ConcurrentHashMap wait for key possible?

i have multithread communication.我有多线程通信。 1 Thread is dispatching datas to other threads. 1 线程正在将数据分派给其他线程。

Main thread is pushing data:主线程正在推送数据:

Main Thread: ConcurrentHashMap map = Global.getInstance().getMap();主线程:ConcurrentHashMap map = Global.getInstance().getMap(); //push data to some other thread map.put(1,"Test"); //将数据推送到其他线程 map.put(1,"Test");

Thread 1: String data = map.get(1);线程 1:字符串数据 = map.get(1); //returns null directly , but i want to wait until data pushed //直接返回null,但我想等到数据推送

Thread 1 returns null if main thread doesn't push any data.如果主线程不推送任何数据,则线程 1 返回 null。 But i want to wait until i got data , how can i wait ?但是我想等到我得到数据,我怎么能等呢?

TransferQueue is not good solution to my current implementation. TransferQueue 不是我当前实现的好解决方案。 I have to do with ConcurrentHashMap.我必须使用 ConcurrentHashMap。

Does someone know any solution?有人知道任何解决方案吗?

You can create a BlockingMap, something like this;你可以创建一个 BlockingMap,像这样; depending on usage, you should also device a mechanism to remove unused keys and queues associated to them in order to avoid a memory leak.根据使用情况,您还应该设置一种机制来删除与它们关联的未使用的键和队列,以避免内存泄漏。

public class BlockingMap<K, V> {
    private final Map<K, BlockingQueue<V>> map = new ConcurrentHashMap<>();

    private synchronized BlockingQueue<V> ensureQueueExists(K key) {
        //concurrentMap.putIfAbsent would require creating a new
        //blocking queue each time put or get is called
        if (map.containsKey(key)) {
            return map.get(key);
        } else {
            BlockingQueue<V> queue = new ArrayBlockingQueue<>(1);
            map.put(key, queue);
            return queue;
        }
    }

    public boolean put(K key, V value, long timeout, TimeUnit timeUnit) {
        BlockingQueue<V> queue = ensureQueueExists(key);
        try {
            return queue.offer(value, timeout, timeUnit);
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        }
    }

    public V get(K key, long timeout, TimeUnit timeUnit) {
        BlockingQueue<V> queue = ensureQueueExists(key);
        try {
            return queue.poll(timeout, timeUnit);
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        }
    }
}

Since Java 8, ensureQueueExists can be written:从 Java 8 开始, ensureQueueExists可以写成:

private synchronized BlockingQueue<V> ensureQueueExists(K key) {
    return map.computeIfAbsent(key, k -> new ArrayBlockingQueue<>(1));
}

You can use BlockingQueue if you allowed to change your implementation, or use a wait/notify technique to wait and run when occupy.如果您允许更改您的实现,您可以使用BlockingQueue ,或者使用等待/通知技术在占用时等待并运行。

String value = null;
while(true) {
    if((value = map.get(1)) != null) { // VARY IMPORTANT to use get and !=
        // work with value 
    } else {
        map.wait(); // should be in a synchronized block.
    }
}

and for producer:对于生产者:

String value = "Test";
map.put(1,value);
map.notifyAll(); // or notify().

First, call wait() on Thread 1 right before it gets a value from the Map.首先,在线程 1 从 Map 获取值之前调用它的wait() You could then extend ConcurrentHashMap and override the put() method to notify() Thread 1 when new data is available.然后,您可以扩展 ConcurrentHashMap 并在新数据可用时覆盖put()方法以notify()线程 1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM