2013-03-20 4 views
0

Когда я вызываю pauseThread(), он всегда выдает IllegalMonitorStateException.Mass IllegalMonitorStateException on thread wait

Я заметил в документации, что мне нужно, чтобы иметь монитор объектов, чтобы заставить поток ждать.

с этой частью кода

synchronized (obj) { 
     while (<condition does not hold>) 
      obj.wait(); 
     ... // Perform action appropriate to condition 
    } 

в этом случае бы OBJ парам быть бегун это время (ServerTickHandler.peakBlockDestructionQueue() == NULL) {} но когда obj.wait(); называется, нужно ли его уведомлять? или будет ли он уведомлять себя, когда условие while не является истинным? будет ли цикл цикла synchronized() {} циклически циклическим или ему понадобится цикл while в synchronized() {}, чтобы выполнить это?

изменить: будет ли syncronized() {} войти внутрь методом run?

Вот мой класс

public class ServerTickSaveHandler implements Runnable 
{ 
    private static Thread runner; 
    /** 
    * Creates a new thread for dealing with logging block destruction when using certain tools. 
    * @param threadName Name of the thread. 
    */ 
    public ServerTickSaveHandler(String threadName) 
    { 
     runner = new Thread(this, threadName); 
    } 
    /** 
    * If thread has nothing to do we shall pause it so it does not needlessly run :D. 
    * @throws InterruptedException 
    */ 
    public void pauseThread() 
    { 
     try 
     { 
      runner.wait(); 
     } 
     catch (InterruptedException e) 
     { 
      e.printStackTrace(); 
     } 
     catch(IllegalMonitorStateException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
    /** 
    * If Items from DropItemQueue need ticking lets resume this thread. 
    * @throws IllegalMonitorStateException 
    */ 
    public void resumeThread() 
    { 
     try 
     { 
      runner.notify(); 
     } 
     catch (IllegalMonitorStateException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
    /** 
    * The thread that is spawned when this object is created. 
    */ 
    public void run() 
    { 
     while (true) 
     { 
      // long start = System.currentTimeMillis(); 

      WorldData worldData = ServerTickHandler.getBlockDestructionQueue(); 
      if (worldData != null) 
      { 
       worldData.saveToFile(); 
      } 
      else pauseThread(); 

      // long end = System.currentTimeMillis(); 

      // NumberFormat formatter = new DecimalFormat("#0.00000"); 
      // Utils.log("Save Tick Handler Execution time is " + 
      // formatter.format((end - start)/1000d) + " seconds"); 
     } 
    } 
    /** 
    * Starts the thread. 
    * @throws IllegalStateException 
    */ 
    public void startThread() 
    { 
     try 
     { 
      runner.start(); 
     } 
     catch (IllegalStateException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

ответ

2

Как указано, вы должны держать монитор объекта, на котором вы называете wait()/notify(). Так как вы вызываете эти методы на runner, эти инструкции должны быть внутри блока

synchronized(runner) { 

.

Сказали, что вызов wait()/notify() на тему довольно странный выбор. Лучше использовать конечный выделенный объект блокировки для ожидания/уведомления. В вашей программе есть и другие плохие варианты. Например, инициализация статического поля из конструктора.

wait() и notify() являются очень низкоуровневыми, простыми в использовании примитивами. Вместо этого вы должны использовать абстракции более высокого уровня, такие как Locks, Semafhores, CountDownLatches, BlockingQueues и т. Д.

+0

Спасибо, сейчас он работает. – JohnM