有效实现此Java MouseListener Logic

时间:2012-01-24 01:45:31

标签: java multithreading swing concurrency event-listener

我有一个MouseListener线程,每次点击时都会调用此方法:

public void mousePressed(MouseEvent event){

    //my Logic here

}

现在发生的事情是,在很短的时间内有太多的点击,而我的逻辑在这里需要更多的时间来处理。我期待的是进一步的点击将被丢弃,这种方法将继续在最近的即将到来的点击。

但是,正在发生的事情是,当逻辑处理时,传入的clics排队,即使点击停止,qued点击继续调用这个mousePressed方法,因此我有多个延迟执行。

不幸的是,我无法控制Listener(为什么它会发出问题并继续发送延迟点击),所以在这种情况下,你能告诉我什么是有效的处理方式,这样我就不会因为延迟我的处理。

我认为最明显的方法是使用另一个线程,但我想知道这可能会在很短的时间内触发这么多线程,或者有什么方法可以锁定一个线程,而其余的点击只是通过空循环?

2 个答案:

答案 0 :(得分:2)

更新:请参阅Phillip关于为什么这对Swing不起作用的评论!

很遗憾,您无法访问eventListener。理想的解决方案是在执行回调时取消注册回调。

这是一个解决方案,模拟在执行时取消注册回调函数,假设您希望排队的点击消失:

private AtomicBoolean engaged = new AtomicBoolean(); // thread-safe boolean

public void mousePressed(MouseEvent event){
    if (!engaged.get()) {
        engaged.set(true);

        // your logic here

        engaged.set(false);
    }
}

AtomicBoolean充当测试和设置锁,防止多个线程同时运行按下的事件回调。在锁定过程中,排队的印刷机将消失。

答案 1 :(得分:1)

一种解决方案是访问用户点击的组件,并在处理MouseListener期间将其禁用。这样它就不会接受新的点击。这样做的另一个好处是可以向用户提供他此时不应该点击该组件的视觉反馈。

您可以通过MouseEvent

访问该组件
public void mousePressed(MouseEvent event) {
  event.getComponent().setEnabled(false);
  try {

    // ....

  } finally {
    event.getComponent().setEnabled(true);
}

一般情况下,你不应该在Swing事件监听器线程中做太多的计算,因为Swing也需要它来处理其他事件和绘画。您应该使用单独的线程来执行实际工作,并在MouseListener中启动它们。您还可以使用ExecutorService来简化此操作。 在整个计算过程中禁用gui组件仍然是个好主意,以便给用户提供反馈。

修改 的 这个解决方案当然取决于Swing。任何类似的解决方案都取决于GUI库的细节,因此如果您使用自己的GUI库,那么您就是自己的GUI库。

您当然可以使用涉及单独线程的通用解决方案来完成工作。我真的推荐ExecutorService,你不需要关心细节,只需提交要执行的任务。然后,您可以使用一个简单的volatile布尔变量来指示当前是否正在执行该操作,并且应忽略新的点击。