在讲线程之前,我们先来谈谈进程。在我接触电脑的一段时间后,开始发现当打开任务管理器后,会有一个进程的显示,下面的映像名称里有很多的可执行文件。这些可执行文件有的是系统默认的,有的是我们打开的,他们都会占用一定内存。
知道了进程,那么什么是线程呢?线程就是运行中程序的调度单位。
我们知道,以前我们写的代码,程序都是从上往下进行,就是必须要执行完上一句才会执行下一句。我们称这种为单线程的程序。那么多线程就是指同时有多个单线程同时进行运作,比如我们今天要做的小球游戏,
如果面板中有多个小球在运动,那么我们就要建立多个小球对象,然后让他们同时运动,但是如果按我们以前的方式,代码从上往下执行,那么想控制多个小球显然很困难,这时我们就要运用到多线程。
讲了那么多,多线程怎么实现呢?
这里有两个方法,一个是继承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起来了~~