Java 等待并通知问题
早些时候,我发布了一个关于实现等待和通知的问题,但我不是很清楚,所以这里有一个更具体的问题 在下面的长代码块中,有一个等待和一个通知。通知应该停止等待并使其停止等待。目前,我认为等待有效,但通知无效。有人能解释一下为什么notify没有通知wait吗?谢谢 注意:代码的其余部分工作正常,我只对这两个特定部分感兴趣Java 等待并通知问题,java,wait,notify,kdb,Java,Wait,Notify,Kdb,早些时候,我发布了一个关于实现等待和通知的问题,但我不是很清楚,所以这里有一个更具体的问题 在下面的长代码块中,有一个等待和一个通知。通知应该停止等待并使其停止等待。目前,我认为等待有效,但通知无效。有人能解释一下为什么notify没有通知wait吗?谢谢 注意:代码的其余部分工作正常,我只对这两个特定部分感兴趣 import com.fmr.ipgt.email.*; import java.io.File; import java.io.IOException; import java.ut
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);
}
}
您正在不同对象上同步。通知将只影响在同一对象和实例上同步的对象 等待线程是同步的&在
NewThread
上等待,而通知线程在MyQuery
实例上等待
拥有一个共享对象
private final Object LOCK = new Object();
synchronized(LOCK){
LOCK.wait();
}
synchronized(LOCK){
LOCK.notify();
}
您正在不同对象上同步。通知将只影响在同一对象和实例上同步的对象 等待线程是同步的&在
NewThread
上等待,而通知线程在MyQuery
实例上等待
拥有一个共享对象
private final Object LOCK = new Object();
synchronized(LOCK){
LOCK.wait();
}
synchronized(LOCK){
LOCK.notify();
}
我建议发布一个精简的示例,它仍然显示了这个问题:没有打印语句,没有异常处理,如果可能的话,没有外部依赖。你应该能把问题的内容减少到10-15行左右。@Matthew不要破坏你问题的内容。让它保持“原样”,以便其他人将来可以从中受益。我建议发布一个精简的示例,该示例仍然显示问题:没有打印语句,没有异常处理,如果可能,没有外部依赖。你应该能把问题的内容减少到10-15行左右。@Matthew不要破坏你问题的内容。让它保持“原样”,这样其他人将来可以从中受益。更好的建议是使用
倒计时闩锁
,不要再担心这种事情了。@MarkoTopolnik虽然使用这样的结构更好,但对他的例子来说,它不起作用。也许是Phaser?我坦率地承认,我并没有投入自己的精力来弄清代码的底细:)我只是非常确信它可以从java.util.concurrent
重新编译成某种东西。谢谢!我很确定它们是在不同的对象上同步的,但我不知道在什么对象上同步了什么。你的代码也有意义!唯一的问题是我把锁的声明放在哪里?在主方法中?@MatthewPiatetsky肯定不是主方法,这会使它成为局部变量。但是我知道你可能指的是Main
类。将其作为公共静态最终
字段。更好的建议是使用倒计时闩锁
,不要再担心这种事情。@MarkoTopolnik尽管使用这样的结构更好,但对他的例子来说,它不起作用。也许是Phaser?我坦率地承认,我并没有投入自己的精力来弄清代码的底细:)我只是非常确信它可以从java.util.concurrent
重新编译成某种东西。谢谢!我很确定它们是在不同的对象上同步的,但我不知道在什么对象上同步了什么。你的代码也有意义!唯一的问题是我把锁的声明放在哪里?在主方法中?@MatthewPiatetsky肯定不是主方法,这会使它成为局部变量。但是我知道你可能指的是Main
类。将其作为公共静态final
字段放在那里。