Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
高效地实现此Java MouseListener逻辑_Java_Multithreading_Swing_Concurrency_Event Listener - Fatal编程技术网

高效地实现此Java MouseListener逻辑

高效地实现此Java MouseListener逻辑,java,multithreading,swing,concurrency,event-listener,Java,Multithreading,Swing,Concurrency,Event Listener,我有一个MouseListener线程,每次单击时都会调用此方法: public void mousePressed(MouseEvent event){ //my Logic here } 现在发生的事情是,在很短的时间内有这么多的点击,而我在这里的逻辑,需要更多的时间来处理。我所期待的是,进一步的点击将被丢弃,这种方法将继续在最新的即将到来的点击 但是,当逻辑在处理时,传入的CLIC会排队,即使单击停止,qued clicks也会继续调用这个鼠标按下的方法,因此我有多个延迟执行

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

public void mousePressed(MouseEvent event){

    //my Logic here

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

但是,当逻辑在处理时,传入的CLIC会排队,即使单击停止,qued clicks也会继续调用这个鼠标按下的方法,因此我有多个延迟执行

不幸的是,我无法控制监听器(为什么它发出que并不断发送延迟的点击),因此在这种情况下,您能否告诉我什么是有效的处理方法,以便我不会因为处理延迟而发出que


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

更新:请参阅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);
    }
}

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

一种解决方案是访问用户单击的组件,并在处理
鼠标侦听器时禁用该组件。这样它就不接受新的点击。这样做还有一个额外的好处,就是给用户视觉反馈,让他在此时不应该点击组件

您可以通过
MouseEvent
访问组件:

public void mousePressed(MouseEvent event) {
  event.getComponent().setEnabled(false);
  try {

    // ....

  } finally {
    event.getComponent().setEnabled(true);
}
一般来说,您不应该在Swing事件侦听器线程中进行太多计算,因为Swing还需要它来处理其他事件和绘制。您应该使用单独的线程来执行实际工作,并在MouseStener中启动它们。您还可以使用ExecutorService来简化此过程。 在整个计算过程中禁用gui组件仍然是一个好主意,以便向用户提供反馈

编辑: 这个解决方案当然取决于Swing。任何类似的解决方案都取决于GUI库的详细信息,因此,如果您使用自己的GUI库,那么您就是自己的GUI库


当然,您可以使用包含独立线程的通用解决方案来完成工作。我真的建议在这里使用
ExecutorService
,如果您不需要关心细节,只需提交要执行的任务即可。然后,您可以使用一个简单的易失性布尔变量,该变量指示操作当前是否正在执行,新的单击是否应被忽略。

您可能希望模拟Swing处理重绘请求的方式—它在请求堆叠时忽略请求。请在此处查看有关此的详细信息:。是的,我想不管怎样,你都会想使用一个后台线程,可能是一个线程池。@hovercraftfullofels,这是一个JNI方法,其中实际的鼠标侦听器来自本机代码,不涉及Swing。好吧,如果我只是启动一个新线程,然后调用该方法,至少我不会错过任何单击,尽管结果仍然是延迟的,并且在许多并行线程中,我想使用一些易失性布尔标志可能是答案,我想是的。这是Swing还是非Swing并不重要,因为原理是相同的。请注意,问题的第一行是错的,MouseListener不是线程。它只是给Swing的一种回调对象,由Swing执行(它恰好在主线程以外的另一个线程上执行,但这并不能使MouseListener本身成为一个线程)。我已经测试过它,但它似乎对输出没有影响,可能是我遗漏了什么,但我会在早上再试一次,现在是凌晨3:30,谢谢这没有效果,因为Swing不是多线程的。所有事件都在同一个线程中顺序执行,因此当调用
mousePressed
方法时,以前的调用总是已经结束。通常,将
已启用。set(false)
调用放入finally块是非常重要的。否则,任何异常或提前返回都将永久禁用该组件。有关(未经测试的)解决方案,请参阅我的答案。谢谢,实际上我无法访问该组件,因为它可能是chrome、windows media player等,我只是挂接到系统dll以获得单击。在我的实现中,所有内容都是基于CLI的,此时不涉及任何Swing GUI,基本上在我的逻辑中,我使用JNA获取活动窗口标题,将其与以前的值进行比较,然后忽略是否相同(对于在同一组件上多次单击),否则,如果活动组件不同,请调用另一个方法。请稍候,你根本不用Swing?你需要在问题中说明这一点。它有一个标记“swing”,并提到了著名的swing类的名称,所以我假设swing就是调用代码的那个。如果不使用Swing,可能就不应该使用Swing类,因为这可能会让未来的代码读者感到非常困惑。因此,现在我已经用一个简单的If(boolean){new Thread().start()}实现了它,在线程中,我将布尔值设置为false,完成后将其设置回true