我有一些响应 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/