Java 弹跳球。为什么每次产生新线程时,球的速度都会加倍?

标签 java multithreading

我想制作一个Java弹跳球程序,可以通过单击“开始按钮”添加多个球。每个球都在自己的线程中,这意味着 10 个球实例 = 10 个线程! 但是当我尝试这样做时,每次创建新线程时,球的速度都会加倍。

我的问题: 1.速度怎么会提升一倍? 2.以及如何让每个球在单独的线程中运行(10个球,10个线程)

    package test3;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test2 extends JFrame{
    int width = 1000;
    int height = 500;
    BallPanel ballPanel = new BallPanel();

    public Test2() {
        setLayout(new FlowLayout(FlowLayout.CENTER, 0, 10));
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));

        JButton start = new JButton("Start");
        start.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ballPanel.start();
            }
        });
        buttonPanel.add(start);

        add(buttonPanel);
        add(ballPanel);
        ini();
    }

    private void ini(){
        setTitle("Test");
        setSize(width, height);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    class BallPanel extends JPanel implements Runnable{
        int panelWidth = 900;
        int panelHeight = 370;
        ArrayList<Ball> ball = new ArrayList<Ball>();

         public BallPanel() {
            setBackground(Color.WHITE);
            setPreferredSize(new Dimension(panelWidth, panelHeight));
        }

        public void start(){
            if (ball.size() < 10) {
                ball.add(new Ball());
            }

            new Thread(this).start();
        }

        public synchronized ArrayList<Ball> movement(ArrayList<Ball> ball){
            for (int i = 0; i < ball.size(); i++) {
                if (ball.get(i).getCurrentX() < 0 || ball.get(i).getCurrentX() > panelWidth - 10) {
                    ball.get(i).setIncrementX(ball.get(i).getIncrementX() * -1);
                } else if (ball.get(i).getCurrentY() < 0 || ball.get(i).getCurrentY() > panelHeight - 10) {
                    ball.get(i).setIncrementY(ball.get(i).getIncrementY() * -1);
                }

                ball.get(i).setCurrentX(ball.get(i).getCurrentX() + ball.get(i).getIncrementX());
                ball.get(i).setCurrentY(ball.get(i).getCurrentY() + ball.get(i).getIncrementY());
            }
            return ball;
        }


        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (ball != null) {
                for (int i = 0; i < ball.size(); i++) {
                    g.setColor(ball.get(i).color);
                    g.fillOval(ball.get(i).getCurrentX(), ball.get(i).getCurrentY(), ball.get(i).getRadius(), ball.get(i).getRadius());
                } 
            }
        }

        @Override
        public void run() {
            while (true) {
                movement(ball);
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {}

                repaint();

            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Test2();
            }
        });
    }

}

球类

package test3;

import java.awt.Color;

public class Ball {
    int currentX;
    int currentY;
    int incrementX;
    int incrementY;
    int radius;
    Color color;



    public Ball() {
        this.currentX = 7;
        this.currentY = 0;
        this.incrementX = 1;
        this.incrementY = 1;
        this.radius = 10;
        this.color = Color.red;
    }

    public int getRadius() {
        return radius;
    }

    public int getIncrementX() {
        return incrementX;
    }

    public void setIncrementX(int incrementX) {
        this.incrementX = incrementX;
    }

    public int getIncrementY() {
        return incrementY;
    }

    public void setIncrementY(int incrementY) {
        this.incrementY = incrementY;
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }

    public int getCurrentX() {
        return currentX;
    }

    public void setCurrentX(int currentX) {
        this.currentX = currentX;
    }

    public int getCurrentY() {
        return currentY;
    }

    public void setCurrentY(int currentY) {
        this.currentY = currentY;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color){
        this.color = color;
    }
}

最佳答案

stop() 正在设置 app = null 并中断线程,但 InterruptedException 被 run() 方法吞没,因此线程继续运行。然后当再次运行start()时,会创建另一个线程,这会导致两个线程都调用movement()方法,从而使移动速度加倍。

关于Java 弹跳球。为什么每次产生新线程时,球的速度都会加倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33832944/

相关文章:

c# - 如何优雅地停止 System.Threading.Timer?

ruby - 停止线程,确保某些最终代码运行

java - 整数数组列表已更改java

java - SQLite 保存日期 12/31/69?

java - 如何使用 JAVA 对 List<String> 中存储的文件名进行自定义排序

java - 如何在加密之前使用 spring security 登录时获取普通用户凭据?

java - Portlet、HttpSession 和线程安全

java - 无法使我的 Http Server 成为多线程?我正在使用 Java HttpServer API

java - 通过多线程读写文件

java - 如何使用 Jackson 从 Json 文件中读取特定对象