如何处理变慢的SwingWorker线程?

问题描述 投票:0回答:1

我几乎不懂多线程的东西。开始研究它,我遇到了一个问题,在我脑海中浮现。我最近写了一个简单的应用程序,一旦我获得了一些关于Java的新知识,我希望用我学到的东西来改进我的应用程序。它看起来像简单的swing GUI,可以在每个时间段更新图像。我实现了ActionListener并覆盖了actionPerformed方法。计时器延迟15ms,重新粉刷JPanelclass,一切正常。但我认为直接在actionPerformed中使用计时器更新我的GUI(我认为它是另一个线程,但我几乎不确定)是个坏主意。所以我决定更改代码并使用SwingWorker。我在process()中调用了我的动画的所有方法..再次app工作正常,但它变得非常慢。现在我在想什么是错的?为什么它比之前更慢?我的定时器延迟实际上并没有等待15ms,即使延迟相同也会慢得多。我在多线程方面犯了错误吗?帮助我理解这些东西。提前致谢

public class GameEngine() extends SwingWorker<Void, Drawable>
GamePanel gp; // ref to JPanel class
{
 public GameEngine(GamePanel gp)
 {
  this.gp = gp;
 }
}
protected void doInBackground()
{
 publish();
}
protected void process(List<Drawable> chunks)
{
 Timer timer = new Timer(15, e ->
 {
  //methods for animation 
  fall();
  animate();
  checkTouch();
 });
}

我留下的一些代码。如果你需要我可以写...

为了清楚我的问题,我提供了一些更多的例子和补充说明。

**以前是: **

public class GamePanel extends JPanel
{
 public void GamePanel()
 {
 GameEngine engine = new GameEngine(this);
 }
 //some images , variables etc...
  protected void paintComponent(Graphics g)
  super.paintComponent(g)
  g.drawImage(image1, x, y, null);
  g.drawImage(image2, w, z,null);
 ...
}
public class GameEngine () implements ActionListener
{
 GamePanel gp;
 Timer timer;
 public void GameEngine(GamePanel gp)
 {
  this.gp = gp;
  timer = new Timer( 15 , this );
 }
 public void actionPerformed()
 {
  //these methods repaint my GamePanel every 15ms.
  fall(); // make object (image) increment on Y Axis 
  animate(); // make another object (image) decrement on X Axis
  checkTouch(); // check if objects collided
 }
}

**成了:**

public class GamePanel extends JPanel
{
 public void GamePanel()
 {
 GameEngine engine = new GameEngine(this);
 }
 //some images , variables etc...
  protected void paintComponent(Graphics g)
  super.paintComponent(g)
  g.drawImage(image1, x, y, null);
  g.drawImage(image2, w, z,null);
 ...
}
public class GameEngine () extends SwingWorker<Void, Drawable>
{
 GamePanel gp;
 Timer timer;
 public void GameEngine(GamePanel gp)
 {
  this.gp = gp;
 }
 protected void doInBackground()
 {
  process();
 }
 protected void progress()
 {
  timer = new Timer (15, e-> 
  {
   new ActionListener(new actionPerformed)
   {
      //these methods repaint my GamePanel every 15ms.
  fall(); // make object (image) increment on Y Axis 
  animate(); // make another object (image) decrement on X Axis
  checkTouch(); // check if objects collided
   }
  });
 }
 protected void done()
 {
 };
}

当我首先创建它时,我实现了ActionListener并通过构造函数中声明的计时器更新了我的面板。我假设它是线程不安全的。这就是为什么我传递所有正在进行的方法,其中我将ActionListener声明为lambda参数。换句话说,我在另一个线程中调用所有动画方法。最后它变慢了,与第一个例子相比......我不明白

  1. Timer是第一个例子EDT还是另一个线程?
  2. 我的第一个例子是线程安全吗?
  3. 为什么我的第二个例子比第一个例子慢得多?

我听说没有在EDT之外更新你的GUI,是不是这样?

java multithreading swing swingworker
1个回答
2
投票

您的问题中没有足够的信息来回答它,但我会对您提出有关多线程以及有关Swing和渲染的隐含问题的疑问,看看我是否可以帮助您。

我认为减速的最可能原因是不必要的屏幕更新。一旦像素被绘制到画布上或应用程序中的任何内容,通常您的应用程序不需要重绘它,除非它应该更改;要么精灵移动,要么应用程序中的某些其他图像暂时遮盖部分图形,然后需要恢复。

新手重新绘制通常会忽略这一点,只需重新绘制整个绘制的表面。虽然这会起作用,但它很慢;如果你在循环中多次这样做,那么循环似乎很慢。

更好的方法是使用传递给重绘例程的矩形,并且仅重新绘制与您的例程重绘的整个表面的交点 - 这会减少需要重绘的部分,因此在时间上需要重绘它。

至于多线程,我认为将它想象成我们过去在单处理器世界中思考事物的方式是有帮助的 - 计算机暂时做了一些事情,然后停在一个你无法预测的地方并在另一个地方做某事一段时间的线程,等等。你不能假设事情将要完成的顺序,或者它将花费多长时间,等等。

使用现代多核计算机,事实上这些事情可能同时完成,但我不知道尝试设想可以帮助你。

© www.soinside.com 2019 - 2024. All rights reserved.