4

我正在开发一个基于 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();
        }
    }

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

谢谢,吉腾

4

2 回答 2

2

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

Thread.currentThread().wait();

lock.wait();

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

编辑:

在这两个地方,也改变

Thread.currentThread().notifyAll();

编辑^2:

解释看这里这里

简而言之:

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

第 1 行中的对象必须与第 2 行中的对象相同因为如果它们不同,则会抛出 IllegalMonitorStateException

抛出以指示线程已尝试在对象的监视器上等待,或通知其他线程在对象的监视器上等待而不拥有指定的监视器。

拥有监视器意味着它需要在同步块内(如第 1,2 行所示)

于 2012-10-06T18:07:18.583 回答
1
synchronized(lock) {
    Thread.currentThread().wait();
}

您遇到异常是因为,您只能调用wait已锁定的对象..在这里您已锁定对象lock..所以应该在锁定时调用等待..

所以,你应该改变你的wait电话lock.wait()

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

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

于 2012-10-06T18:22:26.637 回答