[英]Java - How to wait for an instance to finish before proceeding
在尝试执行其他所有操作之前,我正在尝试等待一段代码返回true。 我有两个类,每个类都运行一个实例。
打开我要等待完成的新对象的主要位置
setupWizard setup = new setupWizard();
setup.setVisible(true);
setup.setCallerRef(new java.lang.ref.WeakReference(this));
synchronized(this) {
while (setup.isItComplete() == false) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ArrayList<String> accounts = Functions.fetchAccounts();
我要等待的SetupWizard
public setupWizard() {
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
//get handlers
JButton helpBtn = (JButton)getContentPane().getComponent(9);
JButton saveBtn = (JButton)getContentPane().getComponent(8);
JTextField userName = (JTextField)getContentPane().getComponent(3);
JTextField serverField = (JTextField)getContentPane().getComponent(1);
JPasswordField passwordField = (JPasswordField)getContentPane().getComponent(5);
JScrollPane scrolly = (JScrollPane)getContentPane().getComponent(7);
JLabel customQLabel = (JLabel)getContentPane().getComponent(6);
scrolly.setVisible(false);
customQLabel.setVisible(false);
//theb change btn positions and action listeners
setBounds(100, 100, 435, 220);
changeHelpButton(helpBtn);
helpBtn.setEnabled(false);
changeSaveButton(saveBtn, userName, serverField, passwordField);
registerAccount("hi", "hi");
}
public void registerAccount(String pass1, String pass2) {
if (pass1.equals(pass2)) {
Functions.addToDatabase("admin", pass2, 1, 1, 1, 1);
}
setComplete(true);
synchronized(getCallerRef()) {
getCallerRef().notifyAll();
}
dispose();
}
private boolean complete = false;
private Object callerRef;
public boolean isItComplete() {
return this.complete;
}
public void setComplete(boolean variable) {
this.complete = variable;
}
public void setCallerRef(Object mycaller) {
this.callerRef = mycaller;
}
public Object getCallerRef() {
return this.callerRef;
}
如您所见,这只是代码的相关部分。 但是,发生的是主线程冻结,但是应该弹出的第二个UI只是一个透明窗口,上面没有任何内容。 可能是什么问题? 还是有其他可行的方法来“直到x变为true为止才阻止代码”?
编辑:
好吧,我想我发现了一个问题; 如果我只是初始化该类,然后立即从第二个类的Initializer方法中调用registerAccount()而不尝试对UI进行任何操作,那么它将起作用。 但是,我并不想立即进入registerAccount(),因为在此之前,用户必须经历一个半长过程才能输入各种数据,之后必须解冻我们的主要对象。 有任何想法吗?
您没有正确使用wait(),但是在执行您想做的事情中可能很有用。
首先,阅读Object.wait上的javadoc
然后,在您当前正在调用的代码中
this.wait()
更改为
synchronized (setup) {
setup.wait();
}
在设置中,将setComplete
更改为
public synchronized void setComplete(Boolean variable) {
this.complete = variable;
if (variable) {
this.notifyAll();
}
}
这是如何进行有效的多线程锁定/等待/同步的基本框架(上面有很多框架)
有两个不同的对象,您调用的notifyAll在WeakReference
对象上,而在您等待Main
对象时。
在setupWizard
类的registerAccount
方法中,您需要进行以下更改,以便在与主锁正在等待锁的对象相同的对象上进行通知。
Object lock = ((WeakReference)getCallerRef()).get(); // this will be object of Main in case its not null.
if( lock != null){
synchronized( lock ) {
lock.notifyAll();
}
}
编辑您的代码中的一个基本问题是您只有一个线程。 同一个线程进入等待状态,同一个线程尝试调用notifyAll
。 如果该线程进入等待状态,则没有线程可以调用notifyAll
,这导致应用程序永远处于挂起状态。 您需要从单独的线程调用setupWizard构造函数。
编辑2您的代码有很多问题。
您需要一个单独的线程来调用registerAccount,以便通知线程与等待线程不同。
您的构造函数当前会调用registerAccount,尝试在锁objct上进行同步,但是在调用构造函数之后,您会从main传递锁对象。
您等待的对象和调用notifyall的对象是不同的对象
从发布的代码中我确实无法确定,但是我怀疑您的情况可能是SetupWizard是框架或对话框,而Main中的代码是由EDT执行的,所以当您在Main中等待EDT时,您会冻结GUI和SetupWizard代码无法执行。
我建议您只对SetupWizard使用模式对话框。 当SetupWizard可见时,它将阻止Main。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.