Java 全速线程上的SwingUtilities.invokeLater
我有一个线程,通过使用SwingUtilities.invokeLater在JFrame上显示更新。线程的速度是可调的,当它设置为全速(更新之间没有休眠)时,我的程序会严重减速。我想问题是我的线程生成了太多JFrame的线程无法使用的SwingUtilities.invokeLater事件。那么,我可以在我的线程上做些什么来删除以前添加但未使用的事件吗?或者我应该使用其他方法来更新JFrame而不使用SwingUtilities.invokeLater吗Java 全速线程上的SwingUtilities.invokeLater,java,multithreading,swing,Java,Multithreading,Swing,我有一个线程,通过使用SwingUtilities.invokeLater在JFrame上显示更新。线程的速度是可调的,当它设置为全速(更新之间没有休眠)时,我的程序会严重减速。我想问题是我的线程生成了太多JFrame的线程无法使用的SwingUtilities.invokeLater事件。那么,我可以在我的线程上做些什么来删除以前添加但未使用的事件吗?或者我应该使用其他方法来更新JFrame而不使用SwingUtilities.invokeLater吗 提前谢谢。这对你来说可能是一份完美的工作
提前谢谢。这对你来说可能是一份完美的工作。您可以发布增量更新,
SwingWorker
将对其进行批处理以解决性能问题:
因为流程方法是在事件调度线程上异步调用的,所以在执行流程方法之前,可能会发生多次对发布方法的调用。出于性能目的,所有这些调用都合并到一个带有串联参数的调用中
要在EDT上运行的代码,可以通过实现
process()
来添加。更新列表将在参数中传递给您。听起来您希望避免使事件调度线程饱和。中讨论的类javax.swing.Timer
,包括“合并多个挂起的ActionEvent
触发”。它可能是调整更新速度的另一种方法
如前所述,
SwingWorker
的频率限制为33 Hz。您可以使用简单的重新绘制()吗?这样做的好处是多个调用合并为一个调用
(补充)
假设您不断更新GPS位置并在两个文本字段中显示它。要执行更新的线程:
run() {
while (keepGoing) {
Point myLocation = computeMyLocation();
locationModel.setLocation(myLocation);
locationComponent.repaint();
}
}
然后,在MyLocationComponent中
@Override
public void paintComponent(Graphics g) {
Point myLocation = locationModel.getLocation();
// you'd really want a NumberFormat
latitudeTextArea.setText(String.valueOf(myLocation.y));
longitudeTextArea.setText(String.valueOf(myLocation.x));
super.paintComponent(g);
}
这样做的好处是将模型从视图中分离出来(如果您将线程视为控制器,那么这就是MVC),并且所有线程都应该可以工作-不需要任何invokeLater()。一个缺点是线程需要知道所有需要更新的JC组件。在“真实”场景中,您可能会从“控制器”(线程)或模型向侦听器触发触发重新绘制的事件
注意:正如@trashgod所指出的,在LocationModel中,
getLocation()
和setLocation()
方法应该是同步的,这样更新就会立即出现。这是一个非常有趣的发现。在你提到SwingWorker有一个计时器支持,而不是每个EDT事件都只是在执行时安排下一个事件时,我和你一样惊讶。同样令人惊讶的是,帧速率如此之低,而且它是不可配置的。@MarkPeters:对于SwingWorker
,避免EDT.+1饱和可能是一个合理的折衷方案。这是调整视图更新速度和同步访问共享数据的正确选择;必须同步对任何共享数据的访问。True。示例中未给出的LocationModel.getLocation()和setLocation()应该同步。我再加一张便条。