我正在尝试使用一个线程来控制弹跳球。我可以添加球,删除球,暂停运动,但当我尝试恢复弹跳球的运动时,notify()/ notifyAll()不起作用。我只想要一个线程来控制在List中添加的球的移动。我很感激一个简单的解释,因为我是一个完整的新手。这是代码:
************************************************
public class BounceBallApp extends JApplet {
public BounceBallApp() {
add(new BallControl());
}
public static void main(String[] args) {
BounceBallApp applet = new BounceBallApp();
JFrame frame = new JFrame();
frame.add(applet); //new line added as per the reference
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Assig_1_Base");
frame.add(applet, BorderLayout.CENTER);
frame.setSize(400, 320);
frame.setVisible(true);
}
}
***************************************************************
public class BallControl extends JPanel {
private BallPanel ballPanel = new BallPanel();
private JButton jbtSuspend = new JButton("Suspend");
private JButton jbtResume = new JButton("Resume");
private JScrollBar jsbDelay = new JScrollBar();
private JButton jbtAddBall = new JButton("+1");
private JButton jbtDeleteBall = new JButton("-1");
public BallControl() {
JPanel panel = new JPanel();
panel.add(jbtSuspend);
panel.add(jbtResume);
panel.add(jbtAddBall);
panel.add(jbtDeleteBall);
ballPanel.add();
ballPanel.setBorder(new javax.swing.border.LineBorder(Color.red));
jsbDelay.setOrientation(JScrollBar.HORIZONTAL);
ballPanel.setDelay(jsbDelay.getMaximum());
setLayout(new BorderLayout());
add(jsbDelay, BorderLayout.NORTH);
add(ballPanel, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
// Register listeners
jbtSuspend.addActionListener(new ActionListener() {
@Override
public synchronized void actionPerformed(ActionEvent e) {
ballPanel.suspend();
}
});
jbtResume.addActionListener(new ActionListener() {
@Override
public synchronized void actionPerformed(ActionEvent e) {
ballPanel.resume();
}
});
jbtAddBall.addActionListener(new ActionListener() {
@Override
public synchronized void actionPerformed(ActionEvent e) {
ballPanel.add();
}
});
jbtDeleteBall.addActionListener(new ActionListener() {
@Override
public synchronized void actionPerformed(ActionEvent e) {
ballPanel.delete();
}
});
jsbDelay.addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
ballPanel.setDelay(jsbDelay.getMaximum() - e.getValue());
}
});
}
}
public class BallPanel extends JPanel {
private int delay = 10;
private List<Ball> ballsArray = Collections.synchronizedList(new ArrayList());
//protected List<Ball> ballsArray = new ArrayList<>();
private int radius = 5;
boolean threadSuspended = false;
public BallPanel() {
start();
}
protected void start(){
Thread t;
t = new Thread(){
@Override
public void run(){
System.out.println("*************");
while (true){
repaint();
try {
Thread.sleep(delay);
synchronized(this){
if (threadSuspended==true) {wait();}
}
} catch (InterruptedException e){
e.getMessage();
}
}
}
};
t.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Ball ball : ballsArray){
g.setColor(ball.color);
if (ball.x < 0 || ball.x > getWidth())
ball.dx *= -1;
if (ball.y < 0 || ball.y > getHeight())
ball.dy *= -1;
ball.x += ball.dx;
ball.y += ball.dy;
g.fillOval(ball.x - radius, ball.y - radius, radius * 2, radius * 2);
}
}
public synchronized void suspend() {
threadSuspended = true;
}
public synchronized void resume() {
threadSuspended = false;
notify();
}
public void setDelay(int delay) {
this.delay = delay;
}
public void add(){
if (threadSuspended==false) ballsArray.add(new Ball());
}
public void delete(){
if (ballsArray.size() > 0 && threadSuspended==false)
ballsArray.remove(ballsArray.size() - 1); // Remove the last ball
}
}
**************************************************
public class Ball {
int x = 0;
int y = 0;
int dx = 2;
int dy = 2;
Color color = new Color(random(255),random(255),random(255));
public static int random(int maxRange) {
return (int) Math.round((Math.random() * maxRange));
}
}
答案 0 :(得分:1)
您有“背景”问题......
您在Thread
...
BallPane
因此,当您致电wait()
时,您实际上是在wait()
上呼叫t
Thread t;
t = new Thread(){
@Override
public void run(){
/*...*/
// this = t
synchronized(this){
// This is the same as saying
// this.wait() or t.wait();
if (threadSuspended==true) {wait();}
}
}
};
但是当您致电notify
时,您正在调用BallPane
的{{1}}方法......
notify
因此,public synchronized void resume() {
threadSuspended = false;
// This is the same as this.notify or BallPane.this.notify()
notify();
}
正在等待t
的监视器锁定,并且您在监视器锁定时调用t
的通知...意味着永远不会通知BallPane
如果您使用共享锁而不是......
t