在Job scheduler中使用wait()时获取IllegalMonitorStateException

时间:2012-10-06 17:44:11

标签: java illegalmonitorstateexcep

我正在开发一个基于Java RMI的项目,该项目有Client-->Job Scheduler--> Server structure

我在Job scheduler类中有两个方法,如下所示。评论解释了每行代码的目的。

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();
        }
    }

我在wait()中第一次调用acceptJob()方法时遇到IllegalMonitorStateException。任何想法,如何解决这个问题。

谢谢, 辞典

2 个答案:

答案 0 :(得分:2)

我不知道您的应用程序在逻辑上是否正确,但更改

Thread.currentThread().wait();

lock.wait();

应该使异常不被抛出。请反馈。

编辑:

在这两个地方,也改变了

Thread.currentThread().notifyAll();

EDIT ^ 2:

有关解释,请查看herehere

简而言之:

synchronized(object) {                        //1
   object.{wait(),notify(),notifyAll()};      //2
}
第1行的

对象必须是第2行中的相同对象,because如果它们不相同则抛出IllegalMonitorStateException

  

抛出此异常表示某个线程试图在对象的监视器上等待,或者在没有指定监视器的情况下通知在对象监视器上等待的其他线程。

其中拥有监视器意味着它需要位于synchronized块内(如第1,2行所示)

答案 1 :(得分:1)

synchronized(lock) {
    Thread.currentThread().wait();
}

你正在获得异常,因为你只能在你锁定的对象上调用wait。在这里你锁定了对象lock ..所以等待应该在锁定时调用..

所以,您应该将wait来电更改为lock.wait()

synchronized(lock) {
        lock.wait();
}

同样的情况是notify,你需要在你拥有locked的对象上调用它。