全速线程上的SwingUtilities.invokeLater

时间:2012-10-28 23:28:55

标签: java multithreading swing

我有一个线程,它通过使用SwingUtilities.invokeLater在我的JFrame上显示更新。线程的速度是可调的,当它设置为全速(更新之间没有睡眠)时,我的程序变得非常慢。我想问题是我的线程生成了太多的SwingUtilities.invokeLater事件,JFrame的线程无法使用。那么我可以在我的线程上做些什么来删除以前添加但未消耗的事件?或者我应该使用其他方法来更新JFrame而不使用SwingUtilities.invokeLater?

提前致谢。

3 个答案:

答案 0 :(得分:4)

SwingWorker这可能是一个完美的工作。您可以发布增量更新,SwingWorker将批处理以解决性能问题:

  

因为在Event Dispatch Thread上异步调用了process方法,所以在执行process方法之前可能会对publish方法进行多次调用。出于性能目的,所有这些调用都合并为一个带有连接参数的调用。

您希望在EDT上运行的代码,您可以通过实施process()来添加。更新列表将在参数中传递给您。

答案 1 :(得分:3)

听起来你想避免使事件调度线程饱和。 How to Use Swing Timers中讨论的课程javax.swing.Timer包括setCoalesce(),其中“合并了多个待审ActionEvent次攻击”。它可能是您更新速度的另一种方式。

如上所述hereSwingWorker限制为33 Hz。

答案 2 :(得分:1)

你能用简单的重绘()吗?这样做的好处是多个调用合并为一个。

(详细说明)

假设您不断更新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()。一个缺点是您的线程需要知道需要更新的所有JComponents。在“真实”场景中,您可能会从触发重新绘制的侦听器触发事件​​,无论是来自“控制器”(您的线程)还是来自模型。

注意:正如@trashgod在LocationModel中指出的那样,getLocation()setLocation()方法应为synchronized,以便立即显示更新。