Условие общего доступа Java между классами создает IllegalMonitorStateException: null
У меня есть структура примерно так:
Lock wrapper - используется для хранения блокировки, состояния и объекта из ответа
public class LockWrapper{
private Lock lock;
private Condition myCondition;
private MyObject myObject;
public LockWrapper(Lock lock, Condition myCondition) {
this.lock = lock;
this.myCondition = myCondition;
}
public Condition getMyCondition() {
return myCondition;
}
public MyObject getMyObject() {
return myObject;
}
public void setObject(MyObject myObject) {
this.myObject = myObject;
}
public Lock getLock() {
return lock;
}
}
Задача - помещается в пул потоков для выполнения. Он инициирует запросы к серверу, а затем ожидает ответа сервера.
public class MyTask implements Runnable{
private Lock lock = new ReentrantLock();
private Condition myCondition = lock.newCondition();
private MyWebSocketAPI api;
public MyTask(MyWebSocketAPI api) {
this.api = api;
}
@Override
public void run() {
lock.lock();
try {
// long randomLong = generateRandomLong();
api.sendRequest(randomLong, new LockWrapper(lock, myCondition));
myCondition.await();
//do something after we got a response
} finally{
lock.unlock();
}
}
}
WebSocket - получает запросы и уведомляет задачи об ответах
public abstract class MyWebSocketAPI extends WebSocketClient {
//...
private Map<Long, LockWrapper> lockWrappers = new ConcurrentHashMap<>();
public void sendRequest(Long id, LockWrapper lockWrapper){
this.lockWrappers.put(id, lockWrapper);
//processRequest
}
@Override
public void onMessage(String message) {
LockWrapper lockWrapper = lockWrappers.get(message.get(0).getAsLong());
lockWrapper.getLock().lock();
try{
lockWrapper.setMyObject(new MyObject(message));
this.lockWrappers.put(message.get(0).getAsLong(), lockWrapper);
lockWrapper.getMyCondition().signalAll();
} finally {
lockWrapper.getLock().unlock();
}
}
//...
}
Линия lockWrapper.getMyCondition().signalAll();
выдает исключение:
java.lang.IllegalMonitorStateException: null
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1954)
Почему мои условия выдают это исключение, когда я пытаюсь уведомить задачи, что мы получили их объекты? Я где-то допустил ошибку или Java не позволяет использовать общие условия?
1 ответ
Это была моя ошибка в Task
, Проблема заключалась в том, что я создавал Lock и Condition как глобальные, так и локальные при запуске метода. Замок и состояние имели одно и то же имя. В некоторых случаях я использовал lock
а в некоторых случаях this.lock
(Но это были два разных замка). В результате в методе onMessage
У меня были Состояние и Замок, которые не были связаны друг с другом. После удаления дубликатов все работает.