2

我正在构建一个 java 应用程序,并且我已经实现了自定义侦听器和事件。现在的问题是有许多事件和侦听器,并且当侦听器处理事件时应用程序 GUI 线程被阻塞。这可以使用事件调度线程解决吗?如果有怎么办?

监听器的代码:

public class ProjectChangeObserver
{
    private List<ProjectChangeListener> listeners = new ArrayList<ProjectChangeListener>();

    public void addProjectChangeListener(ProjectChangeListener l)
    {
        listeners.add(l);
    }

    public void removeProjectChangeListener(ProjectChangeListener l)
    {
        listeners.remove(l);
    }

    public void removeAllProjectChangeListeners()
    {
       listeners.clear();
    }

    public void fireProjectChange(ProjectChangeEvent e)
    {
      if(listeners.size() > 0)
       { 
          ArrayList<ProjectChangeListener> safeCopy = new ArrayList<ProjectChangeListener>(listeners);
          for (ProjectChangeListener cl : safeCopy ) {
              cl.onProjectChange(e);
        }
       } 
     }
}
4

3 回答 3

4

Swing 的特点之一是它是单线程的

但是,没有什么能阻止您产生自己的线程来进行后台处理。只要您只调用revalidate()repaint()然后所有绘图仍将在 Swing 线程中处理。

(请记住,如果您要生成其他线程来执行后台工作,那么volatile如果您希望 Swing 线程看到与您的线程中相同的值,请确保声明您的变量。或者通过另一个侦听器将信息传递回。)

如果您打算在单独的线程中进行绘画本身(例如自定义组件),那么根据具体情况,这是不可能或非常不鼓励的。(一些特殊情况可能允许在自定义线程安全缓冲类中多 CPU 生成场景,但您不太可能这样做)。

如果您发现您Listener的 s 是 CPU/网络密集型的,那么您可能需要考虑谁在做大部分的喊叫和谁在听的架构。我总是尽量减少“视图”代码中的喊叫声,以便它简单地响应事件。

顺便说一句,我发现Project Lombok和它的 Beta 姐妹Lombok PG可以大大减少Listener使用@ListenerSupport.

于 2012-07-30T10:57:27.303 回答
1

恰恰相反,必须避免使用 Event Dispatch Thread 来解决这个问题(“GUI 线程”只是同一事物的另一个名称)。您必须使用SwingWorker它在自己的线程中启动异步任务。

于 2012-07-30T10:47:26.050 回答
1

如果您想防止 UI 阻塞,您应该为您的事件运行单独的线程。

如果您想对事件使用单个线程,那么您可以创建线程,然后可以使用存储事件的队列将命令传递给事件线程。

但是,如果可能,您应该为您的事件打开异步线程,并且您应该确保在需要时刷新 UI。

于 2012-07-30T11:28:15.590 回答