我目前正在编写一个包含一堆按钮的Swing-Interface的小应用程序。现在我的问题如下:启动应用程序后,调用一个方法,我想等待按下两个按钮然后继续正常。我有两个线程,一个是主线程,另一个是创建,只是等到按下两个按钮。对于按钮,我添加了一个像往常一样的ActionListener,它将变量增加1并调用一个方法,当变量为2时唤醒另一个变量。
所以这是我的代码:
int counter = 0;
static Thread thread1;
static Thread thread2;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
thread1 = new Thread() {
@Override
public void run() {
MainFrame frame = new MainFrame();
frame.setVisible(true);
start();
}
};
thread1.start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public MainFrame() {
//other stuff and similar Listeners
JButton button1 = new JButton();
button1.addActionListener(new ActionAdapter() {
@Override
public void actionPerformed(ActionEvent ae) {
count++;
notifyIfTwo();
}
});
}
public void notifyIfTwo() {
if (count == 2) {
synchronized(thread2) {
notifyAll();
}
}
}
public void start() {
thread2 = new Thread() {
@Override
public void run() {
try {
synchronized(thread1) {
thread2.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread2.start();
//other stuff
}
无论我怎么做,我总是得到一个IllegalMonitorStateException。我也试过它在thread2中的一个循环,它将检查计数器是否是两个但我得到了相同的结果。我认为这与同步问题有关,但我对整个多线程的东西都很陌生,所以如果你能给我一些指向正确方向的话,我将不胜感激。
或者你甚至可能知道一个更简单的方法来完成整个“等到按下两个按钮”-problem?
提前感谢,
此致
答案 0 :(得分:3)
使用CountDownLatch
。它允许等待给定数量的countDown()
调用。
Thread.wait();
没有意义,无法编译。 wait
方法可以应用于您正在同步的对象。
答案 1 :(得分:1)
我认为导致异常的原因是thread1正在从UI线程访问GUI组件。解决这个问题的一种方法是摆脱thread1。让你的onClick(或actionPerformed)处理程序增加变量。让thread2在等待后循环并监视变量值(比如500mS)。
所以你可以稍后用runnable保持调用,但是在外部运行方法中做的工作如下:
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try
{
MainFrame frame = new MainFrame();
frame.setVisible(true);
start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void start() {
thread2 = new Thread() {
@Override
public void run() {
try {
while (keepGoing)
{
thread2.sleep(500);
if (variableIncremented)
{
// doSomething();
// reset variable, or set keepGoing = false
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread2.start();
//other stuff
}
答案 2 :(得分:1)
重点是:
synchronized(thread2) {
notifyAll();
}
您正在通知所有等待this
的线程,但您没有this
的监视器。
对于所有wait / notify / notifyAll,代码必须是:
synchronized (foo) {
foo.wait(); // or foo.notify()
}
同样,以后你有:
synchronized(thread1) {
thread2.wait();
}
你不能在obj1上同步并等待obj2,除非obj1 == obj2。
答案 3 :(得分:0)
好的,现在想通了。剩下的问题是我没有将GUI线程和包含逻辑的其他线程严格分开(在我发布的代码之外)。
感谢所有帮助我搞清楚IllegalMonitorStateException的人
我现在像有人建议的那样使用CountDownLatch,它就像一个魅力。