2013.07.25
上课内容:多线程
在讲线程之前,我们先来谈谈进程。在我接触电脑的一段时间后,开始发现当打开任务管理器后,会有一个进程的显示,下面的映像名称里有很多的可执行文件。这些可执行文件有的是系统默认的,有的是我们打开的,他们都会占用一定内存。
知道了进程,那么什么是线程呢?线程就是运行中程序的调度单位。
我们知道,以前我们写的代码,程序都是从上往下进行,就是必须要执行完上一句才会执行下一句。我们称这种为单线程的程序。那么多线程就是指同时有多个单线程同时进行运作,比如我们今天要做的小球游戏,
如果面板中有多个小球在运动,那么我们就要建立多个小球对象,然后让他们同时运动,但是如果按我们以前的方式,代码从上往下执行,那么想控制多个小球显然很困难,这时我们就要运用到多线程。
讲了那么多,多线程怎么实现呢?
这里有两个方法,一个是继承Thread类,一个是实现runnable接口。具体的应用我们在练习中体现。
练习:控制小球的移动,要求:1.小球不能超出边框2.小球相互碰撞,进行反弹.
这个练习首先要求我们掌握基本界面,知道主界面继承JPanel,重写paint方法以保存面板。然后创建小球类,写出构造方法以及get,set方法,继承线程类,重写run方法。最关键的就是小球要在边界处反弹,还有就是小球遇到其他的小球要发生碰撞。最后让线程run起来~~~
首先我们做出小球界面:
public class BallFrame extends JPanel {
// 实例化一个数组对象
private Ball[] ball = new Ball[10];
// 实例化一个随机数对象
private Random r = new Random();
public static void main(String[] args) {
// 实例化一个面板对象
BallFrame bf = new BallFrame();
// 调用initUI方法
bf.initUI();
}
// 界面函数
public void initUI() {
JFrame jf = new JFrame();// 实例化面板对象
jf.setSize(new Dimension(600, 600));// 设置面板大小
jf.setResizable(false);// 设置不可调节大小
jf.setDefaultCloseOperation(3);// 设置关闭按钮
jf.setLocationRelativeTo(null);// 设置窗体居中
this.setBackground(Color.white);// 设置面板背景为白色
jf.setVisible(true);// 设置窗体可见
jf.add(this, BorderLayout.CENTER);// 将面板添加到窗体上
for (int i = 0; i < ball.length; i++) {
// 实例化每个小球对象
ball[i] = new Ball(new Color(r.nextInt(255), r.nextInt(255),
r.nextInt(255)), r.nextInt(550), r.nextInt(550), 50,
r.nextInt(4) + 1, r.nextInt(4) + 1, this, i);
}
for (int i = 0; i < ball.length; i++) {
// 将每个小球线程运行起来
ball[i].start();
}
}
// 重写paint方法
public void paint(Graphics g) {
// 调用父类的paint方法
super.paint(g);
for (int i = 0; i < ball.length; i++) {
// 从ball中获取颜色并设置
g.setColor(ball[i].getcolor());
// 画出小球
g.fillOval(ball[i].getX(), ball[i].getY(), ball[i].getRadiu(),
ball[i].getRadiu());
}
// 调用碰撞函数
collision();
}
// 碰撞函数
private void collision() {
// 距离数组,存储两小球间的距离
double[][] dis = new double[ball.length][ball.length];
for (int i = 0; i < ball.length; i++) {
for (int j = 0; j < ball.length; j++) {
// 计算两个小球间的距离
dis[i][j] = Math.sqrt(Math.pow(ball[i].getX() - ball[j].getX(),
2) + Math.pow(ball[i].getY() - ball[j].getY(), 2));
}
}
for (int i = 0; i < ball.length; i++) {
for (int j = i + 1; j < ball.length; j++) {
if (dis[i][j] < (ball[i].getRadiu() + ball[j].getRadiu()) / 2) {
int t;
// 交换小球x方向的速度
t = ball[i].getVx();
ball[i].setVx(ball[j].getVx());
ball[j].setVx(t);
// 交换小球y方向的速度
t = ball[i].getVy();
ball[i].setVy(ball[j].getVy());
ball[j].setVy(t);
// 确定碰撞后第二个小球的位置
int x2 = ball[j].getX() - ball[i].getX(), y2 = ball[j]
.getY() - ball[i].getY();
ball[j].setX(ball[i].getX() + x2);
ball[j].setY(ball[j].getY() + y2);
} else {
}
}
}
}
}
然后我们创建线程对象Ball继承Thread:
public class Ball extends Thread {
// 初始化一些对象名
private Color color;
private int x, y, radiu, vx, vy;
private BallFrame bf;
private int id;
/**
* 构造函数
*
* @param color小球颜色
* @param x小球横坐标
* @param y小球纵坐标
* @param radiu小球直径
* @param vx小球横向速度
* @param vy小球纵向速度
* @param bf面板
* @param id标志
*/
public Ball(Color color, int x, int y, int radiu, int vx, int vy,
BallFrame bf, int id) {
this.color = color;
this.x = x;
this.y = y;
this.radiu = radiu;
this.vx = vx;
this.vy = vy;
this.bf = bf;
this.id = id;
}
// 重写run方法
public void run() {
super.run();// 调用父类run方法
// 执行无限循环
while (true) {
// System.out.println("第"+id+"个球的x:"+x +" y:"+y);
x += vx;// 改变x的速度
y += vy;// 改变y的速度
// 如果x越界
if (x <= 0 || x + radiu >= bf.getWidth()) {
vx = -vx;// x速度反向
if (x < 0)
x = 0;
else if (x > bf.getWidth() - radiu)
x = bf.getWidth() - radiu;
else {
}
}
// 如果y越界
else if (y <= 0 || y + radiu >= bf.getHeight()) {
vy = -vy;// y速度反向
if (y < 0)
y = 0;
else if (y > bf.getHeight() - radiu)
y = bf.getHeight() - radiu;
else {
}
} else {
}
try {
Thread.sleep(10);// 设置睡眠时间为10ms
} catch (InterruptedException e) {
e.printStackTrace();
}
// 重绘
bf.repaint();
}
}
public Color getcolor() {
return color;
}
public void setcolor(Color color) {
this.color = color;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getRadiu() {
return radiu;
}
public void setRadiu(int radiu) {
this.radiu = radiu;
}
public int getVx() {
return vx;
}
public void setVx(int vx) {
this.vx = vx;
}
public int getVy() {
return vy;
}
public void setVy(int vy) {
this.vy = vy;
}
}
这样我们的小球就run起来了~~