gpt4 book ai didi

java - Java 中巧妙的异步重绘

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:23:13 26 4
gpt4 key购买 nike

我有一个来自 GUI 问题的用例,我想提交给您。

用例

我有一个 GUI,它根据用户在 GUI 中设置的一些参数显示计算结果。例如,当用户移动 slider 时,会触发多个事件,所有事件都会触发新的计算。当用户将 slider 值从 A 调整到 B 时,会触发许多事件。

但是计算可能需要几秒钟,而 slider 调整可以每隔 100 毫秒触发一个事件。

如何编写一个适当的线程来监听这些事件,并对它们进行某种过滤,以便结果的重绘是生动的?理想情况下,你会喜欢这样的东西

  • 一旦收到第一个更改事件就开始新的计算;
  • 如果接收到新事件,则取消第一次计算,并使用新参数开始新的计算;
  • 但要确保最后一个事件不会丢失,因为最后完成的计算必须是具有最后更新参数的计算。

我尝试过的

我的一个 friend (A. Cardona) 提出了更新线程的这种低级方法,可以防止太多事件触发计算。我将其复制粘贴到此处 (GPL):

他把它放在一个扩展 Thread 的类中:

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 框架中对我应该从哪一个开始进行排序。

你们中有人有类似用例的经验吗?

谢谢

最佳答案

如果您使用的是 SwingSwingWorker 会为此提供功能,您不必自己处理线程池。

为每个请求触发一个 SwingWorker。如果有新的请求进来,而 worker 还没有完成,你可以cancel() 它,然后启动一个新的 SwingWorker。关于其他发帖人所说的,我认为 publish()process() 不是您要找的(尽管它们也很有用),因为它们适用于工作人员可能比 GUI 处理事件更快地触发事件的情况。

ThingyWorker worker;

public void actionPerformed(ActionEvent e) {
if( worker != null ) worker.cancel();
worker = new ThingyWorker();
worker.execute();
}

class ThingyWorker extends SwingWorker<YOURCLASS, Object> {
@Override protected YOURCLASS doInBackground() throws Exception {
return doSomeComputation(); // Should be interruptible
}
@Override protected void done() {
worker = null; // Reset the reference to worker

YOURCLASS data;

try {
data = get();
} catch (Exception e) {
// May be InterruptedException or ExecutionException
e.printStackTrace();
return;
}

// Do something with data
}
}

action 和 done() 方法都在同一个线程上执行,因此它们可以有效地检查是否存在现有 worker 的引用。

请注意,这实际上与允许 GUI 取消现有操作相同,只是取消是在触发新请求时自动完成的。

关于java - Java 中巧妙的异步重绘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15412260/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com