【问题标题】:Event Dispatch Thread painting事件调度线程绘画
【发布时间】:2011-12-27 23:08:54
【问题描述】:

只是一个快速的 - 我正在编写 Sega Master System 模拟器。到目前为止的设计是 GUI(JFrame 子类等)通过 EventQueue.invokeLater() 调用在事件调度线程中运行,并且所有仿真器函数在单独的线程中运行。据我了解,这应该是一种很好的做法,因为 EDT 应该初始化和更新 GUI,而 Swing 不是线程安全的。

这引出了一个小问题——控制台在单独的线程(Z80、VDP 等)中运行,而 VDP(当我完成它时)将更新一个 BufferedImage。只要我将此 BufferedImage 标记为“同步”,然后从 EDT 访问它(特别是 GUI 的绘制方法)是否安全?我这样问,否则我将不得不将大量 VDP 逻辑放入绘制方法本身,我宁愿不这样做,因为它会降低整个 GUI 的速度。

我知道一个简单的问题,但我仍然习惯于推动 Java2D 以获得不错的速度动画。值得一提的是,在逻辑线程中调用 repaint() 方法之后,逻辑线程将一直休眠,直到为下一帧传递唤醒,所以我猜这种设计不会对性能造成影响 - 我对吗?

非常感谢, 菲尔·波特

更新我应该使用更好的语言 - VDP 将通过同步的 setter 方法访问 BufferedImage,而 EDT 将通过同步的 getter 方法访问它。

【问题讨论】:

  • 您应该向我们展示一些代码,说明您打算做什么,因为“将 BufferedImage 标记为同步”没有多大意义。方法或代码块可以同步,但类型不能同步。
  • 抱歉,我应该使用更正确的语言 - 我的意思是当 VDP 更新 BufferedImage 时,它​​将通过同步的“setter”方法进行更新,并且当 JFrame 绘制它时 - 它会这样做所以通过同步的“getter”方法。由于在 EDT 中进行绘画时逻辑线程将处于休眠状态,因此 EDT 不应该等待对象上的锁定,因此我认为这应该可以工作。我不确定的原因是网上有很多东西说 GUI 永远不会从另一个线程更新(尽管在这种情况下是 EDT 进行绘画,所以我认为我没问题)。
  • 为什么不简单地使用 SwingUtilities.invokeLater() 将图像从后台线程传递到 EDT?
  • 我认为该方法只允许在 EDT 上安排可运行任务?我想在 EDT 中绘制 BufferedImage,而不是在 EDT 上运行 Runnable 对象。抱歉,如果我误解了您所说的内容。
  • 如果 Runnable 的 run 方法包括绘制图像,则将 runnable 传递给 SwingUtilities.invokeLater 使 EDT 绘制图像。这不是你想做的吗?

标签: multithreading swing java-2d


【解决方案1】:

我认为您不需要使 setter 和 getter 同步,因为它们只能从 EDT 访问。所以让我们退后一步。你说 getter 将从 EDT 访问——所以我们在这里是线程安全的。现在将在 VDP 上运行 setter 方法——为了处理这种情况,我们要调用 invokeLater(参见示例)。查看here了解更多信息。

Runnable updateAComponent = new Runnable() {

    public void run() { 
//this will run in the EDT
component.doSomething(); 

}

};
//this will run in the VDP
SwingUtilities.invokeLater(updateAComponent);

【讨论】:

  • 所以这个解决方案意味着当逻辑线程来更新 BufferedImage 时,它​​只是将更新工作外包给 EDT?没有这样想,但是是的,我认为这会起作用。这确实意味着 BufferedImage 只能从 EDT 访问(即使它是由逻辑线程实例化的)。
猜你喜欢
  • 2017-10-20
  • 2015-11-06
  • 2011-11-11
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 2010-10-31
相关资源
最近更新 更多