Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.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 我的自定义事件是在GUI EDT上触发还是在;“土生土长”;乙二胺四乙酸_Java_Multithreading_Swing_Listeners_Event Dispatch Thread - Fatal编程技术网

Java 我的自定义事件是在GUI EDT上触发还是在;“土生土长”;乙二胺四乙酸

Java 我的自定义事件是在GUI EDT上触发还是在;“土生土长”;乙二胺四乙酸,java,multithreading,swing,listeners,event-dispatch-thread,Java,Multithreading,Swing,Listeners,Event Dispatch Thread,我正在做一个项目,它会进行一些密集的数学计算(矩阵数组、向量等),所以我自然会将工作分解成作业,并将它们提交给CompletionService以并行执行工作 每个作业对象都可以触发事件,在作业开始、结束、进行和/或失败时通知应用程序 目前,每个作业都接收到整个事件侦听器列表的句柄,并简单地进行迭代,将事件对象传递给每个作业(在同一线程中)。这对我来说不太合适,所以我想了解其他人对自定义事件/侦听器进行此类操作的经验 我应该将事件发送到GUI线程吗?有些侦听器可能与GUI相关,也可能与GUI无关

我正在做一个项目,它会进行一些密集的数学计算(矩阵数组、向量等),所以我自然会将工作分解成作业,并将它们提交给CompletionService以并行执行工作

每个作业对象都可以触发事件,在作业开始、结束、进行和/或失败时通知应用程序

目前,每个作业都接收到整个事件侦听器列表的句柄,并简单地进行迭代,将事件对象传递给每个作业(在同一线程中)。这对我来说不太合适,所以我想了解其他人对自定义事件/侦听器进行此类操作的经验

我应该将事件发送到GUI线程吗?有些侦听器可能与GUI相关,也可能与GUI无关,我不希望强制代码的用户必须手动将其事件发送到GUI线程,如下所示:

public class MyFooEventListener implements FooEventListener {
    public void notifyJobStarted(FooEvent evt) {
        // I want to avoid having users of my library write the following, right?
        SwingUtilities.invokeLater(new Runnable(){
            // update GUI here.
        });
    }
}
我不介意写我自己的EventQueue,因为这是为了学校的一个研究项目,我想这是一个很好的并发性练习。只是想弄清楚实现事件驱动系统的“正确”方式是什么,如何正确触发事件,等等。链接到文章/教程和howto也非常感谢

谢谢

编辑:

我的事件模型有多种事件类型,例如
JobStartedEvent
jobendevent
JobProgressEvent
,等等。这是一种糟糕的方法吗?我应该有一个单一的事件类型吗?如果是,我如何向侦听器传递并非所有事件都通用的信息?示例:我想为progress事件传递范围为[0-1]的double,但这不适用于JobFailureEvent之类的事件。处理这个问题的最佳方法是什么

我可以将额外的信息放在“源”对象本身中,但我的源对象本身就是作业对象,我不适合“泄漏”对作业对象的引用,尤其是在作业对象运行时:

FooJob jobObject = (FooJob)event.getSource();
int progressPercent = jobObject.getCurrentProgress() * 100;
progressLabel.setText(progressPercent + "%");

不。在任何需要引发事件的线程上发出事件,并让子系统的用户决定如何处理它们。如果他们希望将结果发送给GUI,很好,如果不希望,他们可以做任何他们想做的事情,例如,将他们排到另一个线程。仅文档“事件在内部线程上引发,事件处理程序不得阻止”


正如你所说,其他任何东西都会给用户带来他们可能不想要的限制。

发布活动的方式有很多,每种方式都有各自的优缺点。如果消费者不一定是GUI,那么您绝对不应该将自己绑定到awt EDT。除非您确定活动消费者将如何工作,否则我将从简单开始并从那里开始。简单的是:同步通知每个消费者。如果这最终延迟了主任务,那么您应该考虑异步通知。如果使用者最终是GUI,则使用者的通知方法应负责调用
SwingUtilities.invokeLater

只有直接影响GUI的线程应位于EDT上。如果有其他线程需要同步,只需使用
synchronized
关键字(在方法或对象上)

Spring具有事件处理功能,您可以定义自定义事件。

感谢您的响应!所以我要做的基本上是实现我自己的EventDispatchThread对象,它“侦听”共享队列。每个作业都将其事件对象放入队列中,我的
FooEventDispatchThread
对象只需将其传递给已注册的每个侦听器。我想下一个问题是我的FooEventDispatchThread应该自己调用侦听器还是使用工作线程来执行此任务?@Kindinos-我想你没有领会这个答案的要点。与我的类似,我相信MartinJames说的是不要使用任何其他线程,而让事件消费者来决定。我所说的是,目前,运行事件侦听器的是作业线程本身。效果如下://为(FooEventListener l:listOfListeners){l.notifyJobProgress(evt,progress);}//继续处理。我担心的是,任何数量的事件侦听器都会长期运行,导致作业本身暂停,直到notifyJobProgress方法返回,从而延迟工作本身的完成。在一个单独的线程中启动侦听器的方法不是更好吗,这样作业线程就可以继续了?