2012-06-29 75 views
3

早些時候,我發佈了一個關於實現等待和通知的問題,但我不是很清楚,所以這裏是一個更具體的問題。等待並通知問題

在下面的長碼塊中有一個等待和一個通知。通知應該停止等待並使其停止等待。目前,我認爲等待有效,但通知不會。有人可以解釋爲什麼通知不通知等待?謝謝!

注意:其餘代碼的作品我只對這兩個特定的部分感興趣。

import com.fmr.ipgt.email.*; 
import java.io.File; 
import java.io.IOException; 
import java.util.List; 
import org.jdom.Document; 
import org.jdom.Element; 
import org.jdom.JDOMException; 
import org.jdom.input.SAXBuilder; 
import javax.mail.MessagingException; 

class MyQuery { 
synchronized void qQuery() throws Exception { 
    String query = ".z.k"; // The query that is used to query q; this can be changed here. 
    int version = 0; 
    c qConn = null; 
    qConn = new c(Main.host,Main.port); // Connect to the q database 
     while (Main.healthy) { 
      Object o = qConn.k(query); // Query q 
      version = c.t(o); 
      if(!(version==0)) { 
       System.out.println(version); 
       System.out.println("database healthy"); 
       NewThread.suspendFlag = false; 
       notify(); 
       break; // End the process if the database responds 
      } 
      } 

     System.out.println("reaches loop end"); 
    } 
} 

class MyThread implements Runnable { 
    MyQuery myResource; 

    MyThread(String name, MyQuery so) { 
    myResource = so; 
    new Thread(this, name).start(); 
    } 

    public void run() { 

    try { 
     myResource.qQuery(); // Begin a method to query q. 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 
} 

class NewThread implements Runnable { 
     String name; // name of thread 
     Thread t; 
     static boolean suspendFlag; 
    private int minutes; 
     NewThread(int minutes) { 
      this.minutes = minutes; 
      System.out.println("reaches constructor"); 
      t = new Thread(this); 
      suspendFlag = true; 
      t.start(); // Start the thread 
     } 
     // This is the entry point for thread. 
     public void run() { 
      try { 
      synchronized(this) { 
       while(suspendFlag) { 

        System.out.println("reaches wait"); 
        wait(minutes*60000); 

        System.out.println("reaches end"); 
        if(suspendFlag) { 
         Main.setHealth(false); 
        Main.sendMessages(); // The database has not responded for the given time. Report that it is unhealthy. 
        } 
        break; 
       } 
       } 
      } catch (InterruptedException e) { 
      System.out.println(name + " interrupted."); 
      } catch (MessagingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     } 
    } 

public class Main { 

private static String[] recipients; 
private static String subject = "Database Failure"; 
private static String message = "The database has failed or is in a hung state"; 
private static String from; 
static String host; 
static int port; 
private static String emails; 
private static int minutes; 
static boolean healthy = true; 
public static void main(String args[]) throws Exception { 

    // Import information from the configuration file 
     SAXBuilder builder = new SAXBuilder(); 
     File xmlFile = new File("/export/home/rhadm/file.xml"); // Note: The directory for the configuration file may need to be changed 

     try { 

     Document document = (Document) builder.build(xmlFile); 
     Element rootNode = document.getRootElement(); 
     List list = rootNode.getChildren("parameters"); 
      Element node = (Element) list.get(0); 

      host = node.getChildText("host"); 
      port = Integer.parseInt(node.getChildText("port")); 
      emails = node.getChildText("emails"); 
      String delims = "[ ]+"; 
      recipients = emails.split(delims); // parse email list 
      minutes = Integer.parseInt(node.getChildText("time")); 
      from = node.getChildText("from"); 

     } catch (IOException io) { 
     System.out.println(io.getMessage()); 
     } catch (JDOMException jdomex) { 
     System.out.println(jdomex.getMessage()); 
     } 
    MyQuery unhealthy = new MyQuery(); 
    NewThread ob1 = new NewThread(minutes); 
    new MyThread("MyThread", unhealthy); // Create new Thread 


    } 
    public static void setHealth(boolean health){ 
     System.out.println("database unhealthy"); 
    healthy = health; 
    } 

    public static void sendMessages() throws MessagingException { 
     System.out.println("sending emails"); 
     FCAPMailSender.postMail(recipients,subject,message,from); 
    } 
    } 
+0

我建議發佈一個下調的例子,仍表現出的問題:沒有打印報表,沒有異常處理,如果可能的話沒有外部的依賴關係。你應該能夠把它降低到大約10-15行。 – david

+0

@Matthew做**不**破壞您的問題的內容。將它保持原樣,以便其他人將來可以從中受益。 – chrisaycock

回答

1

您正在同步不同的對象。通知只會影響同步對象 - 等待同一對象&實例。

的等待線程同步&等待一個NewThread而通知線程這樣做在MyQuery實例

有一個共享對象。

private final Object LOCK = new Object(); 
synchronized(LOCK){ 
    LOCK.wait(); 
} 
synchronized(LOCK){ 
    LOCK.notify(); 
} 
+0

更好的建議是使用'CountDownLatch'並且再也不用擔心這種東西。 –

+0

@MarkoTopolnik儘管使用這樣的結構更好,但它不適用於他的例子。也許是Phaser? –

+0

我毫不猶豫地承認,我沒有投入自己的精力去研究那些代碼的底層:)我只能確定它可以被重寫爲來自'java.util.concurrent'的東西。 –