ConcurrentHashMap wait for key possible?

后端 未结 3 2012
心在旅途
心在旅途 2021-01-13 17:24

i have multithread communication. 1 Thread is dispatching datas to other threads.

Main thread is pushing data:

Main Thread: ConcurrentHashMap map = Glob

相关标签:
3条回答
  • 2021-01-13 17:53

    First, call wait() on Thread 1 right before it gets a value from the Map. You could then extend ConcurrentHashMap and override the put() method to notify() Thread 1 when new data is available.

    0 讨论(0)
  • 2021-01-13 17:59

    You can use BlockingQueue if you allowed to change your implementation, or use a wait/notify technique to wait and run when occupy.

    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().
    
    0 讨论(0)
  • 2021-01-13 18:02

    You can create a BlockingMap, something like this; 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:

    private synchronized BlockingQueue<V> ensureQueueExists(K key) {
        return map.computeIfAbsent(key, k -> new ArrayBlockingQueue<>(1));
    }
    
    0 讨论(0)
提交回复
热议问题