我正在构建一个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);
}
}
}
}
答案 0 :(得分:3)
Swing的一个功能是single-threaded。
但是,没有什么可以阻止您生成自己的线程来进行后台处理。只要您只调用revalidate()
或repaint()
,所有绘图仍将在Swing主题中处理。
(请记住,如果您要生成其他线程来执行后台工作,那么如果您希望Swing线程看到与线程中相同的值,请确保您的变量被声明为volatile
。或者通过信息通过另一个听众回来。)
如果您打算在单独的线程中进行绘制本身(例如自定义组件),则根据情况不可能或非常强烈地阻止它。 (某些异国情况可能允许在自定义线程安全缓冲类中生成多CPU的场景,但您不太可能这样做。)
如果您发现您的Listener
是CPU /网络密集型的,那么您可能需要考虑谁在进行大部分喊叫以及谁正在进行收听的架构。我总是尽量减少我的“视图”代码中的喊叫量,以便它只是响应事件。
顺便说一句,我发现Project Lombok及其Beta姐妹Lombok PG大大减少了使用@ListenerSupport
实施Listener
模式的样板。
答案 1 :(得分:1)
恰恰相反,这必须解决避免事件调度线程(“GUI线程”只是同一事物的另一个名称)。您必须使用SwingWorker
在其自己的线程中启动异步任务。
答案 2 :(得分:1)
如果要阻止UI阻止,则应为事件运行单独的线程。
如果您想为事件使用单个线程,那么您可以创建线程,并且可以使用存储事件的队列将命令传递给事件线程。
但是如果可能的话,您应该为事件打开异步线程,并且应该确保在需要时刷新UI。