2015-01-22 4 views
0

Я пытаюсь реализовать thread wait() и notify(), но метод уведомления не работает, можете ли вы мне помочь? Я хочу, чтобы читательский поток попытался прочитать из своего сообщения; если ящик сообщений пуст, читатель ждет, пока писатель выполнит задание. Но после действия уведомления читатель все еще ждет и ничего не делает, и писатель продолжает свою работу. это мой код (другие пользовательские объекты отлично работает):java-известить тему из темы

public class TrheadTEST { 
    private static class AgentThred implements Runnable {  
     private final String name; 
     private final String category; 
     private final PersonalAgentID agentID; // it has name and category 
     private AgentThred obiettivo; 
     private Thread trd; // i try to call notify for a specific thread. 
     public MessageBox msgx; // each thread has a messagebox. Agent can read only her own messagebox   
     public AgentThred(String nam, String cat){ 
      this.name = nam; 
      this.category = cat; 
      this.agentID = new PersonalAgentID(this.name, this.category); 
      this.msgx.setOwner(this.agentID);    
      this.msgx = new MessageBox(); 
     } 
     public void setObj(AgentThred i) { 
      this.obiettivo = i; 
     } 
     public void setThread(Thread i) { 
      this.trd = i; 
     } 
     @Override 
     synchronized public void run() { 
     { 
//set a message to send 

     if(this.name == "Mercoledi"){ 
      while(true){ 
       // writer write a message in reader messagebox 
       System.out.println("writer wrote"); 
       notifyAll(); //wake up the reader--doesn't work 
       //sleep(500) 
      } 
     } 
     else 
      while(true){ 
       if(this.msgx.imEmpty()){ // if reader messagebox is empty 
        System.out.println("reader can't read"); 
        wait(); //wait until writer put a message in the reader message box 
       } 
       else{ 
        System.out.println("reader can read "); 
        //read the message 
       } 
      } 
    } 
} 
} 
} 
public static void main() { 
    AgentThred agt1 = null; 
    AgentThred agt2 = null; 
    MessageBox msg = new MessageBox(); 
    } 
    agt1 = new AgentThred("Mercoledi","Addams"); 
    agt2 = new AgentThred("Mano","Addams"); 
    Thread t1 = new Thread(agt1); 
    Thread t2 = new Thread(agt2); 
    t2.start(); 
    t1.start(); 
//I need a join here? 
} 
} 
+1

Возможно, вы захотите прочитать [Java Concurrency In Practice] (http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601), если вы собираетесь делать многопоточность. –

ответ

0

Проснуться agt2 от его ожидания, вы должны вызвать notifyAll на тот же объект, как объект, используемый для ожидания. В вашем случае agt2 ждет на this.wait(), поэтому вам нужно будет позвонить agt2.notifyAll(), чтобы разбудить его.

Также обратите внимание, что сравнение строк с == не рекомендуется, даже если это происходит с вашим делом.

Таким образом, вы можете определить:

private static final Object waiter = new Object(); 

и называют:

synchronized(waiter) { 
    waiter.wait(); 
    //or 
    waiter.invokeAll();` 
} 
0

Вам нужен общий объект между двумя, на которых вы можете ждать и уведомлений. Прямо сейчас вы синхронизируете этот экземпляр двух разных потоков и пытаетесь сказать this.wait и this.notify и, следовательно, его не работает.

Для ожидания и уведомления о работе вам необходимо получить мьютексы на одном объекте. См. this.

wait Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0). 
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution. 

Вы можете попробовать пропусканием общий объект для отдельной нити говорят строки и синхронизировать же и ожидание вызова и уведомления с помощью этого объекта. например:

//thread1 
synchronize(myString) { 
    myString.wait(); 
} 

//thread2 
synchronize(myString) { 
    myString.notifyAll(); 
} 
+0

Синхронизация по строке, вероятно, не такая хорошая идея. – assylias

+0

Да, может быть, String может дать некоторую проблему, но это идеальный ответ, который мне нужен. Я благодарю вас. Так что, может быть, это просто фиктивный вопрос, но могу ли я синхронизировать поток с основным? –

+0

Нах, я не думаю, что синхронизация на String (не интернированная строка) - плохая идея. Он неизменен (здесь ничего не делать) и может использоваться в одном экземпляре. – SMA

0

Вы передаете сообщения, поэтому попробуйте использовать классы java.util.concurrent. Создайте LinkedBlockingQueue, общий для обоих потоков, и используйте методы put() и take() для передачи сообщения.

Это позволяет избежать использования синхронизации и блокировки, если сообщения недоступны для чтения или нет места для размещения сообщения. Различные классы дают разные виды поведения, если это не совсем то, что вам нужно.

Смежные вопросы