这里我尝试使用数据包到达时间为传入的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();
}
答案 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();
}
}
});