4

I'm working on a Java RMI based project which has Client-->Job Scheduler--> Server structure.

I have two methods in Job scheduler class as given below. Commenting explains the purpose of each line of code.

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

I'm getting IllegalMonitorStateException at the first call to wait() method in acceptJob(). Any idea, how to resolve this.

Thanks, Jiten

Farnabaz
  • 4,030
  • 1
  • 22
  • 42

2 Answers2

2

I don't know is it logically correct for your application, but changing

Thread.currentThread().wait();

to

lock.wait();

should make the exception not to be thrown. Please, feedback.

EDIT:

in both places, and also change

Thread.currentThread().notifyAll();

EDIT^2:

for explanation look here and here

in short:

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

object from line 1 must be the same object as the one in line 2, because if they are not the same IllegalMonitorStateException is thrown

Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.

where owning the monitor would mean that it needs to be inside the synchronized block (as shown in lines 1,2)

Community
  • 1
  • 1
linski
  • 5,046
  • 3
  • 22
  • 35
  • if u did as described and posted all the relevant code, you should not get IllegalMonitorStateException. What exactly do you mean by "it did not work" - is it not giving the expexted results or is it throwing exception - if so, code and stacktrace, pls – linski Oct 08 '12 at 01:01
1
synchronized(lock) {
    Thread.currentThread().wait();
}

You are getting exception because, you can only call wait upon the object that you have locked.. Here you have lock on the object lock.. So wait should be called on lock..

so, you should change your wait call to lock.wait()

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

Same case is with notify, you need to call it on the object you have locked..

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525