Java 如何处理SwingWorker线程变慢?
我很难理解多线程技术。开始调查时,我遇到了一个问题,这个问题出现在我的脑海里。我最近编写了一个简单的应用程序,一旦我对Java有了一些新的了解,我希望用我学到的知识改进我的应用程序。 它看起来像一个简单的swing GUI,可以在每个时间段更新图像。我实现了ActionListener并重写了actionPerformed方法。计时器延迟15毫秒,重新绘制了JPanel,一切正常。但我认为在actionPerformed中直接使用计时器更新GUI(我认为这是另一个线程,但我几乎不确定)是个坏主意。所以我决定更改代码并使用SwingWorker。我调用了我的动画内部进程()的所有方法。。同样,这个应用程序工作正常,但速度非常慢。 现在我在想怎么了?为什么它的动作比以前慢?我的计时器延迟实际上不是等待15毫秒,虽然延迟相同,但速度要慢得多。我在多线程处理方面出错了吗? 帮我理解这些东西。提前谢谢Java 如何处理SwingWorker线程变慢?,java,multithreading,swing,swingworker,Java,Multithreading,Swing,Swingworker,我很难理解多线程技术。开始调查时,我遇到了一个问题,这个问题出现在我的脑海里。我最近编写了一个简单的应用程序,一旦我对Java有了一些新的了解,我希望用我学到的知识改进我的应用程序。 它看起来像一个简单的swing GUI,可以在每个时间段更新图像。我实现了ActionListener并重写了actionPerformed方法。计时器延迟15毫秒,重新绘制了JPanel,一切正常。但我认为在actionPerformed中直接使用计时器更新GUI(我认为这是另一个线程,但我几乎不确定)是个坏主意
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 () 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()
{
};
}
公共类游戏面板扩展JPanel
{
公众谘询委员会(
{
游戏引擎引擎=新游戏引擎(此);
}
//一些图像、变量等。。。
受保护组件(图形g)
超级油漆组件(g)
g、 drawImage(图像1,x,y,空);
g、 drawImage(图像2,w,z,空);
...
}
公共类GameEngine()扩展了SwingWorker
{
游戏面板gp;
定时器;
公共void游戏引擎(游戏面板总成)
{
this.gp=gp;
}
受保护的void doInBackground()
{
过程();
}
受保护的无效进度()
{
定时器=新定时器(15,e->
{
新建ActionListener(新建actionPerformed)
{
//这些方法每15毫秒重新绘制一次我的游戏面板。
fall();//使对象(图像)在Y轴上递增
animate();//使另一个对象(图像)在X轴上递减
checkTouch();//检查对象是否发生碰撞
}
});
}
受保护的void done()
{
};
}
当我第一次创建它时,我实现了ActionListener,并通过构造函数中声明的计时器更新了我的面板。。我认为这是不安全的。
这就是为什么我传输EverythingProgress方法,其中我将timer和ActionListener声明为lambda参数。
换句话说,我在另一个线程中调用动画的所有方法。
最后,与第一个示例相比,速度变慢了。。
我不明白
我听说没有在EDT之外更新您的GUI,是这样吗?您的问题中没有足够的信息来回答这个问题,但我将回答您关于多线程的问题以及关于Swing和渲染的隐含问题,看看我是否能帮到您 我认为最可能的原因是不必要的屏幕更新。一旦像素被绘制到画布上或应用程序中的任何地方,通常应用程序不需要重新绘制它,除非它应该更改;应用程序中的精灵移动或其他图像会暂时遮挡图形的一部分,然后需要恢复 新手重新绘制时通常会忽略这一点,而只是重新绘制整个绘制表面。虽然这会起作用,但速度很慢;如果你在一个循环中做了很多次,那么这个循环看起来会很慢 更好的方法是使用传递到重画例程中的矩形,只重新绘制其与例程重画的整个曲面的交点——这会减少需要重画的部分,从而减少重画所需的时间 至于多线程,我认为用我们过去在单处理器世界中的思维方式来思考它是很有帮助的——计算机会做一段时间,然后停在一个你无法预测的地方,然后在另一个线程中做一段时间,等等。你不能假设事情的完成顺序,或者在每件事情上花费多长时间,等等
使用现代多核计算机,这些事情实际上有可能同时完成,但我不知道这对你有什么帮助。你的问题中没有足够的信息来回答它,但是我会回答你关于多线程的问题,以及关于Swing和渲染的隐含问题,看看我是否能帮你解决 我认为最可能的原因是不必要的屏幕更新。一旦像素被绘制到画布上或应用程序中的任何地方,通常应用程序不需要重新绘制它,除非它应该更改;应用程序中的精灵移动或其他图像会暂时遮挡图形的一部分,然后需要恢复 新手重新绘制时通常会忽略这一点,而只是重新绘制整个绘制表面。虽然这会起作用,但速度很慢;如果你在一个循环中做了很多次,那么这个循环看起来会很慢 更好的方法是使用传递到重画例程中的矩形,只重新绘制其与例程重画的整个曲面的交点——这会减少需要重画的部分,从而减少重画所需的时间 至于多线程,我认为用我们过去在单处理器世界中的思维方式来思考它是很有帮助的——计算机会做一段时间,然后停在一个你无法预测的地方,然后在另一个线程中做一段时间,等等。你不能假设事情的完成顺序,或者在每件事情上花费多长时间,等等 有了现代多核计算机,这些事情事实上有可能同时完成,但我不知道这对你有什么帮助
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()
{
};
}