在ConcurrentHashMap

时间:2017-08-03 19:21:21

标签: java multithreading concurrency concurrenthashmap

这里我尝试使用数据包到达时间为传入的UDP数据包创建10秒桶,但总是在删除后的10秒内创建多个密钥。

public static void main(String[] args) {
ConcurrentHashMap<Long, String> tenSecondBucket =
    new ConcurrentHashMap<Long, String>();

此线程尝试连续写入哈希映射。添加新条目时,它按键(时间戳)比较旧条目,是否超过10秒,如果是,则创建新条目,否则将更新它。

Thread writingThread = new Thread(new Runnable() {
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1);

                if(tenSecondBucket.size() > 0) {
                    // getting last key
                    long lastKey = 0;
                    for (long keyValue : tenSecondBucket.keySet()) {
                        lastKey = keyValue;
                    }

                    if(System.currentTimeMillis() - lastKey > 10000) {
                        tenSecondBucket.put(System.currentTimeMillis(), "secondEntry");
                    } else {
                        tenSecondBucket.put(lastKey, "updatedEntry");
                    }
                } else {
                    tenSecondBucket.put(System.currentTimeMillis(), "newEntry");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
});

writingThread.start();

此线程删除10秒旧密钥。

Thread removingThread = new Thread(new Runnable() {
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(4000);

                if(tenSecondBucket.size() > 0) {
                    tenSecondBucket.keySet().stream().forEach(key -> {
                        if(System.currentTimeMillis() - key > 10000) {
                            tenSecondBucket.remove(key);
                        }
                    });
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
});

removingThread.start();

这个主题试图阅读那里发生的事情。

Thread readingThread = new Thread(new Runnable() {
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(4000);

                if(tenSecondBucket.size() > 0) {
                    tenSecondBucket.keySet().stream().forEach(key -> {
                        System.out.println("testing key which is timestamp " + key);
                    });
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
});

readingThread.start();

}

1 个答案:

答案 0 :(得分:2)

正如史蒂夫在评论中所说,获取最后一个密钥的方法是不正确的,并且会产生随机值。

您还在评论中提到,对于多个编写器线程,您需要这是线程安全的。

我会尝试以下内容,使用共享的AtomicLong保存“最后一个密钥”,然后使用updateAndGet原子地更新它:

    AtomicLong lastKey = new AtomicLong();
    Thread writingThread = new Thread(() -> {
        while (true) {
            try {
                Thread.sleep(100);
                long now = System.currentTimeMillis();
                long localLastKey = lastKey.updateAndGet(oldValue -> oldValue < now - 10000 ? now : oldValue);
                if (localLastKey == now) {
                    tenSecondBucket.put(now, "newEntry");
                } else {
                    tenSecondBucket.put(localLastKey, "updatedEntry@" + now);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });