java - 忽略重复触发的事件

标签 java events swing concurrency

我有一些响应 PropertyChangeEvent 的代码。此事件的问题在于它可能会连续触发几次或根本不触发。无法预测此事件是仅触发一次还是多次,并且我无法控制此事件的触发方式。我希望事件监听器仅被触发一次。

我对这个问题的解决方案是使用我编写的一个名为DelayedRunnable的类。我将监听器包装在 DelayedRunnable 中。当事件第一次被触发时,监听器被安排在一秒后执行——这是我任意决定的时间。随后的事件触发将被忽略,直到这一秒过去。以下是DelayedRunnable的代码:

public class DelayedRunnable implements Runnable {
    final Runnable                 runnable;
    final int                      delayAmount;
    final TimeUnit                 delayUnit;
    final ScheduledExecutorService service         = new ScheduledThreadPoolExecutor(1);
    final Runnable                 executeRunnable = new ExecuteRunnable();
    final AtomicBoolean            scheduled       = new AtomicBoolean(false);

    public DelayedRunnable(Runnable runnable, int delayAmount, TimeUnit delayUnit) {
        if (runnable == null)
            throw new IllegalArgumentException("runnable == null");
        this.runnable = runnable;
        this.delayAmount = delayAmount;
        this.delayUnit = delayUnit;
    }

    public void run() {
        if (!scheduled.compareAndSet(false, true))
            return;
        service.schedule(executeRunnable, delayAmount, delayUnit);
    }

    class ExecuteRunnable implements Runnable {
        public void run() {
            runnable.run();
            scheduled.set(false);
        }
    }
}

当我将监听器包装在 DelayedRunnable 中时,它仅被调用一次。 DelayedRunnable 的一个附带好处是监听器代码不在 Swing EDT 上执行,因为监听器代码非常昂贵。

但是我发现有时监听器永远不会被调用,可能是由于 DelayedRunnable 中的并发问题。当我重新启动应用程序时,监听器会神奇地再次工作。正如人们所期望的那样,由于并发编程的本质,我无法重现 DelayedRunnable 无法工作的情况。另外,一秒的时间限制是完全任意的。在某些计算机上,一秒钟可能不够。在其他计算机上,一秒太长。没有直接的方法来设置时间限制。

我有两个问题:

  • 有人知道我看不到的 DelayedRunnable 的问题吗?

  • 是否有比采用这种 DelayedRunnable 方法更优雅的方法来处理此问题?

最佳答案

您应该小心的一件事是在 EDT 之外进行 gui 工作。由于实际可运行对象在新线程(执行器服务内部)上运行,因此它无法直接执行任何 gui 工作。

您的一个可运行程序可能会挂起,因此任何 future 的执行都会被阻止。

关于java - 忽略重复触发的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5969296/

相关文章:

java - 相当于 Grails 中的 chain.doFilter

javascript - FlexSlider:如何使用 JS 或 jQuery 在页面加载时获取图像高度?

java - JPanel 没有在 setSize 方法中设置大小

java - 在Thread算法工作期间重绘JPanel

java - JFrame 中显示的 JOptionPane 文本

java - 如何从来自 api 响应的 json 字符串构造对象列表?

java - ArrayList 如何提供随机访问行为?

java - 在 Java 应用程序中检测 Windows 注销事件

c# - 为什么要通过变量引用事件?

java - 禁用主机在 WiFiP2PManager 中接受连接的对话框