我有一个GUI问题的使用案例想提交给您的智慧。
使用案例
我有一个GUI,它显示根据用户在GUI中设置的一些参数计算结果。例如,当用户移动滑块时,会触发多个事件,所有这些事件都会触发新计算。当用户将滑块值从A调整到B时,会触发几十个事件。
但是计算可能需要几秒钟,而滑块调整可以每隔几百毫秒触发一次事件。
如何编写一个适当的线程来监听这些事件,并对其进行过滤,以便结果的重绘是生动的?理想情况下,您希望像这样:
- 收到第一个更改事件后立即启动新计算;
- 如果收到新事件,则取消第一个计算,并使用新参数启动新计算;
- 但确保不会丢失最后一个事件,因为最后一个完成的计算需要是具有最新更新参数的计算。
我尝试过的方法
我的一个朋友(A. Cardona)提出了这种低级方法,即Updater线程,可以防止太多事件触发计算。我在此处复制粘贴它(GPL):
他将其放在一个扩展线程的类中:
public void doUpdate() {
if (isInterrupted())
return;
synchronized (this) {
request++;
notify();
}
}
public void quit() {
interrupt();
synchronized (this) {
notify();
}
}
public void run() {
while (!isInterrupted()) {
try {
final long r;
synchronized (this) {
r = request;
}
// Call refreshable update from this thread
if (r > 0)
refresh(); // Will trigger re-computation
synchronized (this) {
if (r == request) {
request = 0; // reset
wait();
}
// else loop through to update again
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void refresh() {
// Execute computation and paint it
...
}
每当GUI发送事件说明参数已更改时,我们调用
updater.doUpdate()
。 这会导致refresh()
方法被调用的次数少得多。
但我对此没有控制。
还有其他方法吗?
我想知道是否有另一种方法来做到这一点,可以使用jaca.concurrent类。 但是,我无法在Executors框架中排序应该从哪一个开始。
你们中有没有人有类似用例的经验?谢谢
worker1.cancel()
之后是否仍有小概率执行worker1.done()
,并且它可能会在worker2.done()
之后执行,即旧结果会覆盖新结果。这里需要进行更多的调查。 - ZhongYuworker2.doInBackground()
将比worker1.cancel()
花费更长时间。另外,由于cancel()
、execute()
和done()
都在事件分派线程中,所以如果Swing同步正确,cancel()
应该防止调用done()
。这里的取消没有竞争条件。 - Andrew Mao