2

我正在开展一个项目,该项目会进行一些密集的数学计算(矩阵、向量等数组),所以我很自然地将工作分成工作,并将它们提交给 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,因为这是针对学校的一个研究项目,我想这将是一个很好的并发练习。只是想弄清楚实现事件驱动系统的“正确”方式是什么,如何正确触发事件等。文章/教程和操作指南的链接也非常感谢。

谢谢!

编辑:

我的事件模型有多种事件类型,例如JobStartedEvent, JobEndedEvent,JobProgressEvent等。这是一种不好的方法吗?我应该有一个单一的事件类型,如果是这样,我如何将并非所有事件都通用的信息传递给侦听器?示例:我想为进度事件传递 [0-1] 范围内的双精度数,但这不适用于像 JobFailureEvent 这样的事件。处理此问题的最佳方法是什么?

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

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

4 回答 4

4

不。在需要引发它们的任何线程上发出您的事件,并将其留给子系统的用户来决定他们希望如何处理它们。如果他们希望将结果发送到 GUI,那很好,如果没有,他们可以做任何他们想做的事情,例如。将它们排队到另一个线程。只需记录“在内部线程上引发事件并且事件处理程序不得阻塞”。

正如您所说,其他任何事情都会对他们可能不想要的用户施加限制。

于 2012-10-17T18:11:26.247 回答
3

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

于 2012-10-17T18:13:46.280 回答
1

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

于 2012-10-17T18:14:15.097 回答
0

Spring 具有事件处理功能,您可以定义自定义事件http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#context-functionality-events

于 2012-10-17T18:14:24.190 回答