在我继续处理其他所有事情之前,我试图等待一段代码返回true。我有两个类,每个类都有一个实例运行。
Main 我在哪里打开我想等待完成的新对象
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成为真正的&#34;?
修改
好的,我想我发现了这个问题;如果我只是初始化类,然后立即从第二个类的初始化方法调用registerAccount()而不尝试对UI做任何事情,它的工作原理。但是,我不想立即去注册帐户(),因为在此之前,用户必须经过一个半长的程序来输入各种数据,之后主要的我们必须解冻。有任何想法吗?
答案 0 :(得分:0)
你没有正确使用wait(),但它可能对你做你想做的事非常有用。
首先,阅读Object.wait上的javadoc
然后,在您当前正在调用的代码中
this.wait()
将此更改为
synchronized (setup) {
setup.wait();
}
在设置中,将setComplete
更改为
public synchronized void setComplete(Boolean variable) {
this.complete = variable;
if (variable) {
this.notifyAll();
}
}
这是您如何进行高效多线程锁定/等待/同步的基本框架(有很多内置)
答案 1 :(得分:0)
有两个不同的对象,您调用的notifyAll位于WeakReference
对象上,等待Main
的对象。
在registerAccount
类的setupWizard
方法中,您需要进行如下更改,以便在与主线程等待锁定的对象相同的对象上进行通知。
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,它尝试在锁定对象上进行同步,但是在调用构造函数后从main传递锁定对象。
您等待的对象以及您调用notifyall的对象是不同的对象
答案 2 :(得分:0)
我真的无法从您发布的代码中确切地说出来,但我怀疑您的情况可能是SetupWizard是Frame或Dialog而Main中的代码是由EDT执行的,所以当你把EDT打开时在Main中等待你冻结GUI并且SetupWizard代码也不能执行。
我建议您只使用SetupWizard的模态对话框。当SetupWizard可见时,它将阻止Main。