Java 在ConcurrentHashMap中创建多个键而不是一个键
在这里,我尝试使用数据包到达时间为传入的UDP数据包创建10秒bucket,但在删除后的10秒内始终创建多个密钥Java 在ConcurrentHashMap中创建多个键而不是一个键,java,multithreading,concurrency,concurrenthashmap,Java,Multithreading,Concurrency,Concurrenthashmap,在这里,我尝试使用数据包到达时间为传入的UDP数据包创建10秒bucket,但在删除后的10秒内始终创建多个密钥 publicstaticvoidmain(字符串[]args){ ConcurrentHashMap tenSecondBucket= 新的ConcurrentHashMap(); 此线程尝试连续写入哈希映射。添加新条目时,它会按键(时间戳)比较旧条目,是否早于10秒,如果是,则创建新条目,否则将更新它 threadwritingthread=新线程(new Runnable())
publicstaticvoidmain(字符串[]args){
ConcurrentHashMap tenSecondBucket=
新的ConcurrentHashMap();
此线程尝试连续写入哈希映射。添加新条目时,它会按键(时间戳)比较旧条目,是否早于10秒,如果是,则创建新条目,否则将更新它
threadwritingthread=新线程(new Runnable()){
@凌驾
公开募捐{
while(true){
试一试{
睡眠(1);
if(tenSecondBucket.size()>0){
//拿到最后一把钥匙
长lastKey=0;
for(长keyValue:tenSecondBucket.keySet()){
lastKey=keyValue;
}
如果(System.currentTimeMillis()-lastKey>10000){
tenSecondBucket.put(System.currentTimeMillis(),“secondEntry”);
}否则{
tenSecondBucket.put(lastKey,“updateEntry”);
}
}否则{
tenSecondBucket.put(System.currentTimeMillis(),“newEntry”);
}
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
});
writingThread.start();
此线程删除10秒前的密钥
Thread removingThread=新线程(new Runnable()){
@凌驾
公开募捐{
while(true){
试一试{
睡眠(4000);
if(tenSecondBucket.size()>0){
tenSecondBucket.keySet().stream().forEach(键->{
if(System.currentTimeMillis()-键>10000){
tenSecondBucket.移除(键);
}
});
}
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
});
removingThread.start();
这个线程试图读取那里发生的事情
threadingthread=新线程(new Runnable()){
@凌驾
公开募捐{
while(true){
试一试{
睡眠(4000);
if(tenSecondBucket.size()>0){
tenSecondBucket.keySet().stream().forEach(键->{
System.out.println(“测试键,即时间戳”+键);
});
}
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
});
readingThread.start();
}
正如Steve在评论中所说,获取最后一个密钥的方法不正确,将导致随机值
您在评论中还提到,对于多个writer线程,您需要这样才能保证线程安全
我会尝试以下方法,使用共享的AtomicLong
保存“最后一个键”,并使用以下命令进行原子更新:
AtomicLong lastKey=new AtomicLong();
线程写入线程=新线程(()->{
while(true){
试一试{
睡眠(100);
long now=System.currentTimeMillis();
long localLastKey=lastKey.updateAndGet(oldValue->oldValue
正如Steve在评论中所说,获取最后一个密钥的方法不正确,将导致随机值
您在评论中还提到,对于多个writer线程,您需要这样才能保证线程安全
我会尝试以下方法,使用共享的AtomicLong
保存“最后一个键”,并使用以下命令进行原子更新:
AtomicLong lastKey=new AtomicLong();
线程写入线程=新线程(()->{
while(true){
试一试{
睡眠(100);
long now=System.currentTimeMillis();
long localLastKey=lastKey.updateAndGet(oldValue->oldValue
对于(long keyValue:tenSecondBucket.keySet()){lastKey=keyValue;}
在这个代码键集中,如果没有排序,它将为您获取一个随机键,而不是您最后使用的键。更改tenSecondBucket.put(System.currentTimeMillis(),“newEntry”)tolastkey=System.currentTimeMillis();tenSecondBucket.put(lastkey,“newEntry”)代码>我不知道如何设置注释的格式以使其可读。@SteveBauer如果多个线程尝试写入,则我无法存储您描述的最后一个键。这是真的,for(long keyValue:tenSecondBucket.keySet(){If(keyValue>lastKey)lastKey=keyValue;}
可以工作,但仍然会出现争用条件问题。当我试图使用当前毫秒创建一个10秒的存储桶时,我不知道如何解决这个问题。for(long keyValue:tenSecondBucket.keySet()){lastKey=keyValue;}
在这个代码密钥集中,它没有排序,它将得到
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();
}
}
});