1

我正在做一个关于多个球弹跳的学校项目。到目前为止,我设法创建了应用程序,一切正常。但是,我还需要在应用程序中实现多线程,这就是我卡住的地方。我在想一个球一个线程,但我不确定如何实现它。到目前为止,这是我的代码(部分):

public void paintComponent(Graphics g)
        {
            super.paintComponent(g);

            //The balls are painted only after the timer is started
            if(bTimer)
            {
                for(Ball ball:ballList.ballsArrayList) 
                {
                    Thread ballThread = new Thread(ball);
                    ballThread.start();
                    ball.draw(g);

                    /*other code for moving the ball*/
                }
            }
        }

在类 Ball 中:

     public void draw(Graphics g) {
          Color color = new Color(this.getColorR(),this.getColorG(),this.getColorB());
          g.setColor(color);
          int radius = this.getsize();
          g.fillOval((int)(this.getX() - radius), (int)(this.getY() - radius), (int)(2 *     
          radius), (int)(2 * radius));

       }

     public void run() {  

            String name = Thread.currentThread().getName();  

            for (int i = 0; i < 200; i++) {  

                //ball.draw(g); ??

                try {  
                    Thread.sleep(50); 
                    System.out.println("Sleeping");
                } catch (Exception ex) {}  
            }  
        }  

我在想我可以将 ball.draw() 函数放在线程的 run() 函数中。但我不知道我该怎么做,或者这是否是个好主意。多线程对我来说仍然很难理解和实现 =((

4

2 回答 2

2

不是一个真正的答案,但太长了,无法发表评论。

您应该注意 Swing不是线程安全的。所有 Swing 组件都应该在 Event Dispatch Thread 上访问,并且只能在该线程上访问。有关更多信息,请参阅Swing 中的并发指南。

这意味着每个球可以有一个线程来更新球的位置。但是,如果您在绘画期间访问球的位置,则此访问发生在 EDT 上。这意味着您无法随时更新背景线程中球的位置。您将不得不实施一些锁定或简单地更新 EDT 上的位置。

我不确定你想达到什么目标,但如果你只是想在特定时间间隔更新球的位置,我会选择javax.swing.Timer. 此计时器在 EDT 上触发,允许您以线程安全的方式更新位置。Swing wiki 标记包含更多用于在 Swing 中实现动画的链接。

于 2012-11-02T10:38:35.233 回答
1

所有 swing 代码都必须在事件调度线程上运行。因此,您在代码片段中所做的事情很糟糕。

但是,如果计算球的位置是 CPU 密集型的并且需要时间,您确实希望将逻辑移动到单独的线程中,否则您的 UI 将变得无响应。

这将成为一个典型的生产者/消费者问题:一个线程产生坐标,事件调度线程通过绘制球来消耗它们。

于 2012-11-02T11:04:47.143 回答