【问题标题】:Better way to make a thread sleep使线程休眠的更好方法
【发布时间】:2016-11-12 23:34:04
【问题描述】:

我一直在编写有关 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 只执行循环。

【问题讨论】:

  • Netbeans 可能不明白你为什么使用Thread.sleep() 并给你一个错误的提示。
  • 我自己也在想——非常合理的解释。

标签: java multithreading swing netbeans thread-sleep


【解决方案1】:

虽然我已经找到了几种更好的方法

你不认为你应该告诉我们你找到的方法,这样我们就不会花时间提出你已经知道的建议吗?我们不是读心者,我们无法猜测您尝试了什么。

我一直无法找到一种在不弄乱代码的情况下包含它们的方法。

好吧,无论如何你的代码都应该重新设计。

代码的动画应该是游戏面板的函数,而不是 main() 方法。因此,您应该在面板中内置startGame()stopGame() 之类的方法,您可以调用它们。

Netbeans 提示我执行 thread.sleep 会影响性能。

是的,通常您不应该使用 Thread.sleep(),因为通常代码是由于某些用户操作而执行的,并且代码在 Event Dispatch Thread (EDT) 上执行。由于 EDT 负责绘制 GUI,如果您一直告诉它休眠,那么这显然会影响性能。

但是,在您的情况下,循环逻辑未在 EDT 上执行,因此它不应该是一个问题(除了整体设计问题)。

实际上,您不应该使用循环。相反,您应该使用Swing Timer 来安排动画。

还可以查看教程中关于Concurrency in Swing 的部分,该部分将详细解释EDT 以及为什么应在EDT 上更新Swing 组件。

【讨论】:

    【解决方案2】:

    您可以使用ScheduledExecutorService 每10 秒调用一次moveBall()paint(),而不是在Thread.sleep(10) 中使用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);
    
        }    
    }
    

    【讨论】:

    • 您不应该从paintComponent 覆盖进行绘画吗? Reference:Swing programs should override paintComponent() instead of overriding paint().
    • 其实是取自OP,我这里的回答只关注在没有Thread.sleep(10)的情况下更好的方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 2013-01-28
    • 2014-06-01
    相关资源
    最近更新 更多