我正在尝试编写一个线程安全结构来保留键值对并在一定时间延迟后自动删除它们。问题是,容器应该通知其他线程有关删除的信息。
我还尝试在同步块(synchronized block)中使用 notifyAll()
,但问题仍然存在。
import java.util.Objects;
import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class Container <K extends Comparable<K>, V> {
private ConcurrentHashMap <K, V> a;
private final int delay = 2;
private final Lock lock = new ReentrantLock();
private final Condition removed = lock.newCondition();
public Container() {
a = new ConcurrentHashMap<>();
}
public synchronized void put(K k, V o) {
lock.lock();
a.put(k, o);
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(delay);
a.remove(k, o);
removed.signalAll();
lock.unlock();
} catch (InterruptedException e){
e.printStackTrace();
}
}).start();
}
public V get(int k) {
return a.get(k);
}
@Override
public String toString() {
return Stream.of(a)
.filter(Objects::nonNull)
.map(Object::toString)
.collect(Collectors.joining(", ", "{", "}"));
}
}
public class Main {
public static void main(String [] args) throws InterruptedException {
Container<Integer, Integer> c = new Container<>();
c.put(0, 10);
System.out.println(c);
c.put(1, 11);
c.put(2, 12);
TimeUnit.SECONDS.sleep(3);
System.out.println(c);
}
}
程序以代码0
结束并打印预期值:第一个元素和空结构。但无论哪种方式,我都得到了 IllegalMonitorStateException
。
任何想法,谢谢。
最佳答案
我们这里有一些事情需要注意:
-
lock
-
removed
这是使用lock
创建的条件
您的主线程获取 lock
上的锁在 put
方法。
然而它永远不会释放锁;相反,它会创建一个新的 Thread
调用 removed.signalAll()
。然而这个新线程没有持有锁lock
这是需要这样做的。
我认为你需要做的是确保每个锁定 lock
的线程也解锁它并且每个线程调用 signalAll
还有一个锁。
public synchronized void put(K k, V o) {
a.put(k, o);
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(delay);
lock.lock(); // get control over lock here
a.remove(k, o);
removed.signalAll();
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
关于java - 结构如何正确通知其他线程有关事件的信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57140379/