java多线程的程序设计

阅读和修改一个球的代码程序,完成多球的功能:
Write a program that bounces balls inside a panel.The ball should begin moving with a mousePressed event. When user clocks the mouse, a ball should be added. When balls hits the edge of the panel,it should bounde off the edge and continue in the opposite direction.
The ball location should be updated using Runnable.
GUI as follows:图片说明
程序如下:
import java.util.Random;

public class Ball implements Runnable {
private int x; // horizontal position of ball
private int y; // vertical position of ball
private int dx; // change in horizontal position of ball
private int dy; // change in vertical position of ball
private final int MAX_X = 200; // horizontal edge of JPanel
private final int MAX_Y = 200; // vertical edge of JPanel
private static final Random generator = new Random();

public Ball(int xPos, int yPos) {
dx = generator.nextInt(5) + 1; // change in x (1-5 pixels)
dy = generator.nextInt(5) + 1; // change in y (1-5 pixels)
x = xPos; // set ball to horizontal position of mouse press
y = yPos; // set ball to vertical position of mouse press
}

// bounces ball perpetually until window is closed
public void run() {
while (true) {// infinite loop {
try {
Thread.sleep(20); // sleep for 20 milliseconds
}
// process InterruptedException during sleep
catch (InterruptedException exception) {
exception.printStackTrace();
}

     x += dx; // determine new x-position
     y += dy; // determine new y-position

     // if bounce off top or bottom of JPanel
     if (y <= 0 || y >= MAX_Y - 10) {
        dy = -dy; // reverse velocity in y direction
     }

     // if bounce off left or right of JPanel
     if (x <= 0 || x >= MAX_X - 10) {
        dx = -dx; // reverse velocity in x direction
     }
  } 

}

// get horizontal position of ball
public int getX() {
return x; // return x value
}

// get vertical position of ball
public int getY() {
return y; // return y value
}
}

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JPanel;
import javax.swing.JFrame;

public class BallPanel extends JPanel {
private Ball blueBall; // bouncing ball
private ExecutorService threadExecutor; // for running Ball runnable
private JFrame parentWindow; // parent window of JPanel
private final int MAX_X = 200; // horizontal edge of JPanel
private final int MAX_Y = 200; // vertical edge of JPanel

public BallPanel(JFrame window) {
parentWindow = window; // set parent window of JPanel

  // create ExecutorService for running ball runnable
  threadExecutor = Executors.newCachedThreadPool();

  // anonymous inner class handles mouse events
  this.addMouseListener(
     new MouseAdapter() {
        public void mousePressed(MouseEvent event) {
           createBall(event); // delegate call to ball starter
           RepaintTimer timer = new RepaintTimer(parentWindow);
           threadExecutor.execute(timer);
        }
     } 
  ); 

}

// create a ball if no ball exists and set it in motion
private void createBall(MouseEvent event) {
if (blueBall == null) {// if no ball exists {
int x = event.getX(); // get x position of mouse press
int y = event.getY(); // get y position of mouse press
blueBall = new Ball(x, y); // create new ball
threadExecutor.execute(blueBall); // set ball in motion
}
}

// return minimum size of animation
public Dimension getMinimumSize() {
return getPreferredSize();
}

// return preferred size of animation
public Dimension getPreferredSize() {
return new Dimension(MAX_X, MAX_Y);
}

// draw ball at current position
public void paintComponent(Graphics g) {
super.paintComponent(g);

  if (blueBall != null)  {// if ball exists {
     g.setColor(Color.blue); // set color to blue
     g.fillOval(blueBall.getX(), blueBall.getY(), 10, 10); // draws
  }

}
}

import javax.swing.JFrame;

public class BouncingBall extends JFrame {
private final BallPanel ballCanvas; // JPanel in which ball bounces

public BouncingBall() {
ballCanvas = new BallPanel(this); // create new BallPanel
add(ballCanvas); // add BallPanel to JFrame

  pack(); // make window just large enough for its GUI
  setVisible(true); // show window

}

public static void main(String args[]) {
BouncingBall application = new BouncingBall();
application.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}

import javax.swing.JFrame;

public class RepaintTimer implements Runnable {
private final JFrame repaintComponent;

public RepaintTimer(JFrame frame) {
// specify component to be repainted
repaintComponent = frame;
}

public void run() {
while (true) {
try {
Thread.sleep(20);
}
catch (InterruptedException ex) {
ex.printStackTrace();
}

     repaintComponent.repaint(); // repaint the component
 }

}
}

每个小球就是一个线程,生成出来,然后,随机函数写个,随机落在图上各个地方。

老哥,这个问题并不适合使用线程池.线程池是为了完成大量的执行时间短的任务,避免频繁地创建和销毁线程二设计的.
而你的问题,若每个球的运行是一直持续的,那么它并不是执行时间短的任务,需要为其单独创建线程.

实现方法:

  • 多线程,每个线程负责计算单个球的运动轨迹
  • 主线程负责读取所有球的当前位置,并更新UI显示.

线程太多影响性能,统一用一个线程就好,刷新UI用主线程

线程太多影响性能,统一用一个线程就好,刷新UI用主线程