我正在主线程中创建 JFrame 的新对象并调用其调用 wait() 的函数。我想唤醒这个主线程。
public static void main(String[] args) throws Exception {
//some other large code
var loginWin = new LoginWin();
loginWin.setVisible(true);
loginWin.waitForLogin();
System.out.println("Login Finished");
//code after login
}
LoginWin 扩展了 JFrame 并具有带有这样的操作监听器的按钮
login.bsubmit.addActionListener(actionEvent -> {
dataRecived();
});
dataRecived() 函数:-
private void dataRecived() {
passwd = login.passwd.getPassword();
username = login.username.getText();
iphost = login.iphost.getText();
port = 9999;
try {
Integer.parseInt(login.port.getText());
} catch (Exception e) {
e.printStackTrace();
}
notify();
}
但是当我单击 login.bsubmit 按钮时,我收到以下异常:-
Exception in thread "AWT-EventQueue-0" java.lang.IllegalMonitorStateException
at java.base/java.lang.Object.notify(Native Method)
at smit.quiz.server.LoginWin.dataRecived(LoginWin.java:52)
at smit.quiz.server.LoginWin.lambda$new$1(LoginWin.java:34)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1967)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2308)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6632)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3342)
at java.desktop/java.awt.Component.processEvent(Component.java:6397)
at java.desktop/java.awt.Container.processEvent(Container.java:2263)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5008)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4840)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4918)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4547)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4488)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2307)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2762)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4840)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
最佳答案
抛出此异常是因为您调用 Object.notify()没有“持有对象监视器”,即从 synchronized
block 外部或带有 synchronized
修饰符的实例方法:
<小时/>This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways:
- By executing a synchronized instance method of that object.
- By executing the body of a synchronized statement that synchronizes on the object.
- For objects of type Class, by executing a synchronized static method of that class.
Only one thread at a time can own an object's monitor.
Throws:
IllegalMonitorStateException - if the current thread is not the owner of this object's monitor.
也就是说,尝试以未明确设计的方式从其他线程修改 swing 对象是一个坏主意,请参阅 swing package docs :
Swing's Threading Policy
In general Swing is not thread safe. All Swing components and related classes, unless otherwise documented, must be accessed on the event dispatching thread.
[...]
As all events are delivered on the event dispatching thread, care must be taken in event processing. In particular, a long running task, such as network io or computational intensive processing, executed on the event dispatching thread blocks the event dispatching thread from dispatching any other events. While the event dispatching thread is blocked the application is completely unresponsive to user input. Refer to SwingWorker for the preferred way to do such processing when working with Swing.
More information on this topic can be found in the Swing tutorial, in particular the section on Concurrency in Swing.
我建议阅读这些文档,它们包含几个示例,解释如何使用 swing 实现响应式 UI。
关于java - 如何从actionEvent监听器通知主线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56729928/