Получение IllegalMonitorStateException при использовании wait() в планировщике заданий
Я работаю над проектом на основе Java RMI, который имеет Client-->Job Scheduler--> Server structure
,
У меня есть два метода в классе планировщика заданий, как указано ниже. Комментирование объясняет назначение каждой строки кода.
private ConcurrentLinkedQueue<Job> jobQueue;
private ConcurrentLinkedQueue<ComputeServerRef> serverQueue;
private final Object lock = new Object();
/**
* Accepts newly generated job from client and schedule it with idle Compute
* Server or queue it in JobQueue depending on the availability of idle
* Compute Server in serverQueue.
*
* @param job Job object
*
* @exception RemoteException
* Thrown if any remote remote error occurred.
*/
public Job acceptJob(Job job) throws RemoteException
{
// Report a "Job scheduled" to all Loggers.
eventGenerator.reportEvent(new JobSchedulerEvent
("Job "+job.getJobName()+" scheduled"));
synchronized(lock)
{
while(true)
{
if (!serverQueue.isEmpty())
{
// If serverQueue is not empty then get one server from it,
// remove it from the server queue and assign it a new job.
ComputeServerRef csr = serverQueue.poll();
try
{
job = csr.performJob(job);
updateServerStatus(csr);
break;
}
catch(RemoteException re)
{
continue;
}
}
else
{
jobQueue.add(job);
try{
Thread.currentThread().wait();
}catch(InterruptedException e){
e.printStackTrace();
System.out.println("Thread Interrupted");
}
// Check if it's the turn of current thread's job.
// If not then goto wait();
while (!jobQueue.peek().getJobName().equals(job.getJobName()))
{
try{
Thread.currentThread().wait();
}catch(InterruptedException e){
e.printStackTrace();
System.out.println("Thread Interrupted");
}
}
job=jobQueue.poll();
}
}
}
return job;
}
/**
* Adds newly started compute server to serverQueue
*
* @param csr reference of the remote object ComputeServer.
*
* @exception RemoteException
* Thrown if any remote remote error occurred
*/
public void updateServerStatus(ComputeServerRef csr)throws RemoteException
{
synchronized(lock)
{
serverQueue.add(csr);
Thread.currentThread().notifyAll();
}
}
Я получаю IllegalMonitorStateException при первом вызове wait()
метод в acceptJob()
, Есть идеи, как это решить.
Спасибо, Джитен
2 ответа
Я не знаю, логично ли это правильно для вашего приложения, но меняю
Thread.currentThread().wait();
в
lock.wait();
следует сделать исключение, чтобы не быть брошенным. Пожалуйста, оставьте отзыв.
РЕДАКТИРОВАТЬ:
в обоих местах, а также изменить
Thread.currentThread().notifyAll();
EDIT^2:
для объяснения смотрите здесь и здесь
короче:
synchronized(object) { //1
object.{wait(),notify(),notifyAll()}; //2
}
объект из строки 1 должен быть тем же объектом, что и объект в строке 2, потому что если они не совпадают, генерируется исключение IllegalMonitorStateException
Брошенный, чтобы указать, что поток попытался ждать на мониторе объекта или уведомить другие потоки, ожидающие на мониторе объекта, не имея указанного монитора.
если владение монитором будет означать, что он должен находиться внутри синхронизированного блока (как показано в строках 1,2)
synchronized(lock) {
Thread.currentThread().wait();
}
Вы получаете исключение, потому что вы можете только позвонить wait
на объект, который вы заблокировали.. Здесь у вас есть замок на объекте lock
.. так что ждать нужно вызвать на замок..
Итак, вы должны изменить свой wait
позвонить lock.wait()
synchronized(lock) {
lock.wait();
}
Тот же случай с notify
нужно вызвать его на объекте у вас есть locked
..