我有一个类MyModel
,其中包含一个属性datalogEnabled
(和其他一些,但让我们从那里开始),我希望能够正确实现它以用于UI /视图绑定。
public class MyModel {
static final String KEY_DATALOG_ENABLED = "datalogEnabled";
final private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
final private Object syncLock = new Object();
final private Datalogger datalogger = new Datalogger();
public void addPropertyChangeListener(PropertyChangeListener pcl)
{
this.pcs.addPropertyChangeListener(pcl);
}
public void removePropertyChangeListener(PropertyChangeListener pcl)
{
this.pcs.removePropertyChangeListener(pcl);
}
public boolean isDatalogEnabled()
{
synchronized (this.syncLock)
{
return this.datalogEnabled;
}
}
public void setDatalogEnabled(final boolean enable) {
boolean old;
synchronized (this.syncLock) {
old = this.datalogEnabled;
this.datalogEnabled=enable;
}
/* begin snippet X: this is wrong for threading reasons */
this.pcs.firePropertyChange(KEY_DATALOG_ENABLED, old, enable);
setDatalogEnabledNow(enable);
/* end snippet X */
}
setDatalogEnabledNow(boolean b)
{
this.datalogger.setEnable(b);
}
/* other methods */
}
public class Datalogger() {
public void setEnable(boolean enable) { ... }
}
除了代码片段X,这个似乎正确,但我不确定。让我感到震惊的是,访问/设置/监听属性的各种方式可能发生在不同的线程上,而我需要做的是在某处(在一些文件I / O中执行)datalogEnabled
属性我的Datalogger类,在Swing UI线程之外的另一个线程上,因为我不希望UI线程无响应。
如何正确重写代码段X?
在我的整体计划中,我有一个ExecutorService
的实例。我可以在ExecutorService
类中添加Executor
(MyModel
的超类)作为构造函数参数,并为代码段X执行此操作:
this.pcs.firePropertyChange(KEY_DATALOG_ENABLED, old, enable);
this.executor.execute(new Runnable() {
@Override public void run() { setDatalogEnabledNow(enable); }
});
我是否应该将firePropertyChange
调用放入延迟的Runnable任务中? (应该立即调用firePropertyChange,或者在属性更改后真正生效)
或者Datalogger类也应该有一个Executor
,以便它可以协调各种任务吗?
我对这个感到困惑....
答案 0 :(得分:1)
模型的侦听器可以是uis组件或域组件。如果一个监听器是一个ui组件,它必须在edt上运行,而不是在监听器是域的情况下运行。
该事件来自ui组件或域组件。如果事件来自ui组件,则fire方法位于edt上,如果事件来自域,则不是。
所以它有点复杂......我的观点是每个听众应该为自己工作:如果不是,ui听众会继续使用edt,如果不存在,则域名不会。所以fire方法保留在它的原始线程上。
2 cts。