让线程休眠的更好方法
Better way to make a thread sleep
我一直在 Java 8 中编写有关 2D 图形的教程,当时 NetBeans 提示我执行 Thread.Sleep
会影响性能。然而,尽管我已经能够找到几种更好的方法,但我一直无法找到一种方法来包含它们而不会使您的代码混乱。
package platformer;
import java.awt.*;
import javax.swing.*;
import java.util.Scanner;
@SuppressWarnings("serial")
public class Platformer extends JPanel {
int x = 0;//Sets the starting coords. of the ball
int y = 0;
private void moveBall() {//How much the ball moves by
x = x+1;
y = y+1;
}
@Override
public void paint(Graphics g) {//Essentially al the graphics functions
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, 30, 30);
}
public static void main(String[] args) throws InterruptedException {
Scanner reader = new Scanner(System.in);
Scanner reader1 = new Scanner(System.in);
System.out.print("Enter an x-value for the window (whole numbers only): ");
int setx = reader.nextInt();
System.out.print("Enter a y-value for the window (whole numbers only): ");
int sety = reader.nextInt();
JFrame gameFrame = new JFrame("Sample Frame");//Makes the window variable w/ the name in quotations.
Platformer game = new Platformer();//'Copies' the graphics functions above into a variable
gameFrame.add(game);//Adds the above variable into th window
gameFrame.setSize(setx,sety);//Sets the resolution/size of the window(x,y)
gameFrame.setVisible(true);//Makse the window visible
gameFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//Makes the window close when the close button is hit
while (true){
game.moveBall();
game.repaint();
Thread.sleep(10);
}
}
}
我想知道如何包含一种更好的方法让线程在循环中休眠,或者让 NetBeans 只执行循环。
除了在 while(true)
中使用 Thread.sleep(10)
,您还可以使用 ScheduledExecutorService
每 10 秒调用一次 moveBall()
和 paint()
,如下所示给出了更简洁的方式,如下所示:
public class Platformer extends JPanel implements Runnable {
int x = 0;//Sets the starting coords. of the ball
int y = 0;
public void add() {
JFrame gameFrame = new JFrame("Sample Frame");//Makes the window variable w/ the name in quotations.
Platformer game = new Platformer();//'Copies' the graphics functions above into a variable
gameFrame.add(game);//Adds the above variable into th window
gameFrame.setSize(setx,sety);//Sets the resolution/size of the window(x,y)
gameFrame.setVisible(true);//Makse the window visible
gameFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//Makes the window close when the close button is hit
}
private void moveBall() {//How much the ball moves by
x = x+1;
y = y+1;
}
@Override
public void paint(Graphics g) {//Essentially al the graphics functions
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, 30, 30);
}
@Override
public void run() {
//this code will be executed for every 10 seconds
moveBall();
paint();
}
public static void main(String[] args) throws InterruptedException {
Scanner reader = new Scanner(System.in);
Scanner reader1 = new Scanner(System.in);
System.out.print("Enter an x-value for the window (whole numbers only): ");
int setx = reader.nextInt();
System.out.print("Enter a y-value for the window (whole numbers only): ");
int sety = reader.nextInt();
JFrame gameFrame = new JFrame("Sample Frame");//Makes the window variable w/ the name in quotations.
Platformer game = new Platformer();//'Copies' the graphics functions above into a variable
gameFrame.add(game);//Adds the above variable into th window
gameFrame.setSize(setx,sety);//Sets the resolution/size of the window(x,y)
gameFrame.setVisible(true);//Makse the window visible
gameFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//Makes the window close when the close button is hit
//schedule it to run for every 10 seconds
//this calls the run() method above
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(game, 0, 10, TimeUnit.SECONDS);
}
}
though I've been able to find several better ways
嗯,你不认为你应该告诉我们你找到的方法,这样我们就不会花时间提出你已经知道的建议吗?我们不是介意读者,我们无法猜测您尝试了什么。
I haven't been able to find a way to include them without messing u the code.
好吧,你的代码无论如何都应该重新设计。
代码的动画应该是游戏面板的函数,而不是 main() 方法。因此,您应该在可以调用的面板中内置 startGame()
和 stopGame()
等方法。
Netbeans gave me a hint that doing thread.sleep would affect performance.
是的,通常您不应该使用 Thread.sleep(),因为通常代码是作为某些用户操作的结果执行的,并且代码在 Event Dispatch Thread (EDT)
上执行。由于 EDT 负责绘制 GUI,如果您一直告诉它休眠,那么这显然会影响性能。
但是,在您的情况下,循环逻辑未在 EDT 上执行,因此这应该不是问题(整体设计问题除外)。
实际上你不应该使用循环。相反,您应该使用 Swing Timer 来安排动画。
另请查看 Concurrency in Swing
教程中的部分,该部分将详细说明 EDT
以及为什么应在 EDT
上更新 Swing 组件。
我一直在 Java 8 中编写有关 2D 图形的教程,当时 NetBeans 提示我执行 Thread.Sleep
会影响性能。然而,尽管我已经能够找到几种更好的方法,但我一直无法找到一种方法来包含它们而不会使您的代码混乱。
package platformer;
import java.awt.*;
import javax.swing.*;
import java.util.Scanner;
@SuppressWarnings("serial")
public class Platformer extends JPanel {
int x = 0;//Sets the starting coords. of the ball
int y = 0;
private void moveBall() {//How much the ball moves by
x = x+1;
y = y+1;
}
@Override
public void paint(Graphics g) {//Essentially al the graphics functions
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, 30, 30);
}
public static void main(String[] args) throws InterruptedException {
Scanner reader = new Scanner(System.in);
Scanner reader1 = new Scanner(System.in);
System.out.print("Enter an x-value for the window (whole numbers only): ");
int setx = reader.nextInt();
System.out.print("Enter a y-value for the window (whole numbers only): ");
int sety = reader.nextInt();
JFrame gameFrame = new JFrame("Sample Frame");//Makes the window variable w/ the name in quotations.
Platformer game = new Platformer();//'Copies' the graphics functions above into a variable
gameFrame.add(game);//Adds the above variable into th window
gameFrame.setSize(setx,sety);//Sets the resolution/size of the window(x,y)
gameFrame.setVisible(true);//Makse the window visible
gameFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//Makes the window close when the close button is hit
while (true){
game.moveBall();
game.repaint();
Thread.sleep(10);
}
}
}
我想知道如何包含一种更好的方法让线程在循环中休眠,或者让 NetBeans 只执行循环。
除了在 while(true)
中使用 Thread.sleep(10)
,您还可以使用 ScheduledExecutorService
每 10 秒调用一次 moveBall()
和 paint()
,如下所示给出了更简洁的方式,如下所示:
public class Platformer extends JPanel implements Runnable {
int x = 0;//Sets the starting coords. of the ball
int y = 0;
public void add() {
JFrame gameFrame = new JFrame("Sample Frame");//Makes the window variable w/ the name in quotations.
Platformer game = new Platformer();//'Copies' the graphics functions above into a variable
gameFrame.add(game);//Adds the above variable into th window
gameFrame.setSize(setx,sety);//Sets the resolution/size of the window(x,y)
gameFrame.setVisible(true);//Makse the window visible
gameFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//Makes the window close when the close button is hit
}
private void moveBall() {//How much the ball moves by
x = x+1;
y = y+1;
}
@Override
public void paint(Graphics g) {//Essentially al the graphics functions
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, 30, 30);
}
@Override
public void run() {
//this code will be executed for every 10 seconds
moveBall();
paint();
}
public static void main(String[] args) throws InterruptedException {
Scanner reader = new Scanner(System.in);
Scanner reader1 = new Scanner(System.in);
System.out.print("Enter an x-value for the window (whole numbers only): ");
int setx = reader.nextInt();
System.out.print("Enter a y-value for the window (whole numbers only): ");
int sety = reader.nextInt();
JFrame gameFrame = new JFrame("Sample Frame");//Makes the window variable w/ the name in quotations.
Platformer game = new Platformer();//'Copies' the graphics functions above into a variable
gameFrame.add(game);//Adds the above variable into th window
gameFrame.setSize(setx,sety);//Sets the resolution/size of the window(x,y)
gameFrame.setVisible(true);//Makse the window visible
gameFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//Makes the window close when the close button is hit
//schedule it to run for every 10 seconds
//this calls the run() method above
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(game, 0, 10, TimeUnit.SECONDS);
}
}
though I've been able to find several better ways
嗯,你不认为你应该告诉我们你找到的方法,这样我们就不会花时间提出你已经知道的建议吗?我们不是介意读者,我们无法猜测您尝试了什么。
I haven't been able to find a way to include them without messing u the code.
好吧,你的代码无论如何都应该重新设计。
代码的动画应该是游戏面板的函数,而不是 main() 方法。因此,您应该在可以调用的面板中内置 startGame()
和 stopGame()
等方法。
Netbeans gave me a hint that doing thread.sleep would affect performance.
是的,通常您不应该使用 Thread.sleep(),因为通常代码是作为某些用户操作的结果执行的,并且代码在 Event Dispatch Thread (EDT)
上执行。由于 EDT 负责绘制 GUI,如果您一直告诉它休眠,那么这显然会影响性能。
但是,在您的情况下,循环逻辑未在 EDT 上执行,因此这应该不是问题(整体设计问题除外)。
实际上你不应该使用循环。相反,您应该使用 Swing Timer 来安排动画。
另请查看 Concurrency in Swing
教程中的部分,该部分将详细说明 EDT
以及为什么应在 EDT
上更新 Swing 组件。