Java 我的自定义事件是在GUI EDT上触发还是在;“土生土长”;乙二胺四乙酸
我正在做一个项目,它会进行一些密集的数学计算(矩阵数组、向量等),所以我自然会将工作分解成作业,并将它们提交给CompletionService以并行执行工作 每个作业对象都可以触发事件,在作业开始、结束、进行和/或失败时通知应用程序 目前,每个作业都接收到整个事件侦听器列表的句柄,并简单地进行迭代,将事件对象传递给每个作业(在同一线程中)。这对我来说不太合适,所以我想了解其他人对自定义事件/侦听器进行此类操作的经验 我应该将事件发送到GUI线程吗?有些侦听器可能与GUI相关,也可能与GUI无关,我不希望强制代码的用户必须手动将其事件发送到GUI线程,如下所示:Java 我的自定义事件是在GUI EDT上触发还是在;“土生土长”;乙二胺四乙酸,java,multithreading,swing,listeners,event-dispatch-thread,Java,Multithreading,Swing,Listeners,Event Dispatch Thread,我正在做一个项目,它会进行一些密集的数学计算(矩阵数组、向量等),所以我自然会将工作分解成作业,并将它们提交给CompletionService以并行执行工作 每个作业对象都可以触发事件,在作业开始、结束、进行和/或失败时通知应用程序 目前,每个作业都接收到整个事件侦听器列表的句柄,并简单地进行迭代,将事件对象传递给每个作业(在同一线程中)。这对我来说不太合适,所以我想了解其他人对自定义事件/侦听器进行此类操作的经验 我应该将事件发送到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方法返回,从而延迟工作本身的完成。在一个单独的线程中启动侦听器的方法不是更好吗,这样作业线程就可以继续了?