У меня есть стиль клиент-сервер.Что я сделал, так это создал класс RequestController
, который контролирует и контролирует все запросы к серверу, выполненные в виде потокового объекта.
Эти потоки запросов отслеживаются в синхронизированном Map
(создан с помощью Collections.synchronizedMap(new HashMap<Long, RequestThread>())
).Каждые полсекунды проверяется каждый поток запроса, если он все еще жив, он отправляет сообщение о ходе выполнения своему заинтересованному объекту прослушивателя (атрибут потока запроса), если он завершил или потерпел неудачу, он уведомляет заинтересованный прослушиватель и удаляет себя из синхронизированного Map
когда завершается метод run()
.
Объект RequestThread
, который я использую для отслеживания каждого запроса, является защищенным внутренним классом объекта RequestController
, который отслеживает все запросы.Так что у него есть доступ к карте, которая его содержит.
Именно здесь у меня возникают проблемы.Я получаю параллельные исключения при модификации, когда «мертвая нить» удаляется с карты.Весь мой доступ к карте синхронизирован, поэтому я не понимаю, как получить исключение.
Вот код цикла управления:
this.reqTimer = new Timer("Request Timer", true);
TimerTask reqTask = new TimerTask()
{
@Override
public void run()
{
synchronized(reqList)
{
for(RequestThread rt : reqList.values())
rt.updateProgress();
}
}
};
this.reqTimer.scheduleAtFixedRate(reqTask, 500L, 500L);
В самом конце RequestThread.run()
метод есть вызов метода RequestController
для удаления себя с карты следующим образом:
public void removeRequest(long id)
{
synchronized(this.reqList)
{
this.reqList.remove(id);
}
}
Похоже, что если RequestThread.run()
завершается, пока метод TimerTask.run()
проходит по картезапросов на вызов метода updateProgress()
удаление не блокируется, но разрешено изменять карту и вызывать мое исключение.Как два разных потока могут блокировать один и тот же объект одновременно?Разве удаление не должно быть заблокировано, поскольку оно происходит в другом потоке до завершения обновления?