Java 使用同步方法禁用事件侦听器
我的GUI应用程序具有[重新]加载Java 使用同步方法禁用事件侦听器,java,swing,Java,Swing,我的GUI应用程序具有[重新]加载JTable实例数据的方法(例如File->New,File->Open菜单项)。加载或清空项时,事件侦听器处于活动状态,并开始处理处于未定义状态的对象,因此引发异常并与加载操作冲突 我想在加载操作期间停止侦听器。因此,我认为一种解决方案是使加载和侦听器方法同步 我拥有的是一些JTable的实例,侦听器是一个TableModelListener。因此,例如,当单击File->New时,它会触发以下方法: private synchronized void new
JTable
实例数据的方法(例如File->New
,File->Open
菜单项)。加载或清空项时,事件侦听器处于活动状态,并开始处理处于未定义状态的对象,因此引发异常并与加载操作冲突
我想在加载操作期间停止侦听器。因此,我认为一种解决方案是使加载和侦听器方法同步
我拥有的是一些JTable
的实例,侦听器是一个TableModelListener
。因此,例如,当单击File->New
时,它会触发以下方法:
private synchronized void newFileClicked() {
// empty all tables in the application
}
在冲突的侦听器中:
class MyModelListener implements TableModelListener {
@Override public void tableChanged(TableModelEvent tme) {
synchronized (this) {
// do stuff
}
}
}
但是,当调用newFileClicked
方法时,该方法和tableChanged
方法同时输出
我对synchronized
的理解是否错误?或者这个实现是不正确的
两者都可以吗=/
编辑:回答后更正的执行也有相同的症状
Object lock = new Object();
private void newFileClicked() {
synchronized (lock) {
// empty all tables in the application
}
}
class MyModelListener implements TableModelListener {
@Override public void tableChanged(TableModelEvent tme) {
synchronized (lock) {
// do stuff
}
}
}
// Still does not work ! =/
您似乎在不同的对象上使用了
synchronized
synchronized
仅当锁定在完全相同的对象上时才会被阻止
事实上,Swing是超级线程。将使用限制在AWT事件调度线程(EDT)-使用java.AWT.EventQueue.invokeLater
。如果你需要其他的线,确保它们不会碰到任何东西。将数据复制到EDT上的EDT和从EDT复制数据。系统级事件(如MouseEvents或KeyEvents)添加到事件调度线程(EDT)的末尾,并按顺序处理
Swing级别的事件(如TableModelEvent)在生成事件时进行处理。即事件未添加到EDT
我想在加载操作期间停止侦听器
您需要执行以下操作:
或者,您可以使用一个布尔变量,如“loading”,然后让每个侦听器检查您当前是否正在“loading”,如果是,则跳过处理。我的代码中关于此错误的观点很好。为了进行更正,我在主类中添加了一个字段,
final private Object lock=new Object()
,并将其传递到内部类中的synchronized(lock){}
块中。还在newFileClicked
方法中添加了synchronized(lock){}
块。然而,在纠正这一点之后,同样的“不同步”行为仍然会发生=/谢谢,我知道这些不同的方法。我更关心的是理解为什么synchronized
不起作用。基本上你是说同步的方法和块在Swing中不起作用?为了确保与侦听器或线程同步,必须使用另一种方法,如布尔标志?我要说的是,没有任何东西可以同步,因为所有代码都在EDT上执行,所以它已经是单线程的了。当代码在多个线程上执行时,将使用同步。如果TableModelEvent是一个真正的系统事件,那么它将被添加到EDT的末尾,以便在清除表中的所有数据后执行,但它不是一个真正的事件,并且一旦从TableModel中清除数据,就会调用侦听器代码。