如何在bouncing balls程序中使用Java线程池?
我有一个程序,它是一个窗口,有20个弹跳球(线程),随机生成大小、速度、方向和位置。它们还具有随机生成的最大反弹次数,可以对墙进行反弹。当超过该数值时,如何在bouncing balls程序中使用Java线程池?,java,multithreading,swing,threadpool,Java,Multithreading,Swing,Threadpool,我有一个程序,它是一个窗口,有20个弹跳球(线程),随机生成大小、速度、方向和位置。它们还具有随机生成的最大反弹次数,可以对墙进行反弹。当超过该数值时,线程停止工作。 我的问题是如何将ThreadPool合并到程序中,以便当一个Thread停止工作时,启动一个新线程而不是它 public class BouncingBalls extends JPanel{ private ArrayList<Ball> balls = new ArrayList<Ball>(
线程
停止工作。
我的问题是如何将ThreadPool
合并到程序中,以便当一个Thread
停止工作时,启动一个新线程而不是它
public class BouncingBalls extends JPanel{
private ArrayList<Ball> balls = new ArrayList<Ball>();
private static final long serialVersionUID = 1L;
private static final int box_width = 1000;
private static final int box_height = 800;
public BouncingBalls() {
this.setPreferredSize(new Dimension(box_width, box_height));
createBalls();
gameStart();
}
public void createBalls(){
for(int i=0;i<20;i++){
Ball ball = new Ball(this);
balls.add(ball);
}
}
public void gameStart() {
Thread gameThread = new Thread() {
public void run() {
for(Ball b : balls){
b.start();
}
}
};
gameThread.start();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for(Ball b : balls){
b.draw(g2d);
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Bouncing Balls");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new BouncingBalls());
frame.pack();
frame.setVisible(true);
}
});
}
}
public class Ball extends Thread{
private Ellipse2D.Double thisBall;
private int posX;
private int posY;
private int radius;
private int maxBounces;
private int bounces = 0;
private int deltaX, deltaY;
private BouncingBalls mainWindow;
public Ball(BouncingBalls mainWindow){
this.posX = 0 + (int)(Math.random() * ((975 - 0) + 1));
this.posY = 0 + (int)(Math.random() * ((775 - 0) + 1));
this.radius = 6 + (int)(Math.random() * ((20 - 6) + 1));
this.deltaX = -10 + (int)(Math.random() * 21);
this.deltaY = -10 + (int)(Math.random() * 21);
this.maxBounces = 10 + (int)(Math.random() * ((25 - 10) + 1));
this.mainWindow = mainWindow;
thisBall = new Ellipse2D.Double(posX, posY, radius, radius);
}
public void draw(Graphics2D g2d){
g2d.setColor(Color.RED);
g2d.fill(thisBall);
g2d.setColor(Color.BLACK);
mainWindow.repaint();
}
public void run(){
while(true){
int oldx = (int) thisBall.getX();
int oldy = (int) thisBall.getY();
int newx = oldx + deltaX;
if (newx + radius > 995 || newx <= 5){
deltaX = -deltaX;
bounces++;
}
int newy = oldy+ deltaY;
if (newy + radius > 795 || newy <= 5){
deltaY = -deltaY;
bounces++;
}
thisBall.setFrame(newx, newy, radius, radius);
this.posX = newx;
this.posY = newy;
mainWindow.repaint();
if(bounces>=maxBounces){
this.stop();
}
try {
Thread.sleep(30);
}
catch (InterruptedException e){
System.out.println("Woke up prematurely");
}
}
}
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
}
公共类BouncingBalls扩展了JPanel{
private ArrayList balls=new ArrayList();
私有静态最终长serialVersionUID=1L;
专用静态最终整型框_宽度=1000;
专用静态最终整流罩高度=800;
公众弹跳球{
此.setPreferredSize(新尺寸(框宽、框高));
createBalls();
gameStart();
}
公共void createBalls(){
对于(int i=0;i 995 | | newx 795 | | newy=maxBounces){
这个。停止();
}
试一试{
睡眠(30);
}
捕获(中断异常e){
System.out.println(“过早醒来”);
}
}
}
public int getPosX(){
返回posX;
}
公共无效setPosX(int posX){
this.posX=posX;
}
公共int getPosY(){
返回posY;
}
公共无效设置位置(整数位置){
this.posY=posY;
}
}
如果您的目标是在超出maxBounces
后继续运行弹跳球动画线程,只需重置计数即可:
if(bounces >= maxBounces) {
// log the maxBounces exceeded message
bounces = 0;
// this.stop(); - don't do this, Thread#stop() is deprecated
// thread will continue until explicitly interrupted
}
如果您想使用ThreadPool
来使用它,那么在完成Ball#run()
后,您必须安排新的Ball作业(runnable)并将其添加到ThreadPool
。因此,您必须这样做:
球实现可运行(或可调用),而不是扩展线程
MaxBounches
情况即将停止时,您需要将相同的runnable添加到池中:
if (bounces >= maxBounces) {
// reset the counter
bounces = 0;
executor.submit(this);
return;
}
希望这会有所帮助。不确定为什么要使用线程来执行此操作。请记住,Swing不是线程安全的,因此更新需要与EDT同步,并且绘制和更新应该同步,以便在绘制球时不更新球。看看java.util.concurrncy包中的ExecutorService,我同意@MadProgrammer。每个球使用一根线可能是不必要的,而且重量很重。我建议更改您的实现,这样“球”就不会扩展线程,而是只有一个“游戏线程”更新所有球,并在每次迭代中重新绘制每个球。这是这些类型游戏的常见做法。在任何情况下,您都会遇到问题,因为您的代码不是线程安全的。在访问球成员变量(即
thisBall
)之前,您需要在Swing线程和球线程之间进行同步。引用的KineticModel
使用单个javax.Swing.Timer
来调整动画的速度。您在回答之前的问题时有一个问题,请使用Swing Timer而不是线程
if (bounces >= maxBounces) {
// reset the counter
bounces = 0;
executor.submit(this);
return;
}