多线程之赛跑游戏
在corejava的课程中,有一个重要的知识点,就是线程。
那什么是线程呢?线程,是“进程”中某个单一顺序的控制流。而进程和流程的最大区别就在于,每个进程都会独享一块存储区域,多个线程只能共享此进程的这块存储区域。
那线程会给我们的java程序带来什么好处呢?好处一,可以实现并行,好处二,可以更有效的利用资源。
下面我们就编写一个小小的赛跑游戏来看看线程给我们程序带来的惊喜吧。 首先,咱们先看看程序最后完成的效果,及操作流程:
游戏一开始将直接进入主题,简洁的界面,无需说明文档,一眼便知如何操作。(见图1)
图1:游戏一开始的界面
选择好我们要支持的运动员后,点击确定按钮,此时游戏还没有开始,但我们已不可再改变支持的对象了。(见图2)
图2:下注后的界面
好吧,既然不能更改,那么就让比赛快点开始吧!“蜗牛,加油!加油!”(见
图3)
图3:游戏开始后的界面
哦也!蜗牛赢了!看到了吗,结果就在图4里,哈哈哈,点击确定后,400分就拿到手了!
图4: 出结果后的界面
真是一场痛快的比赛!
现在,咱们来进行一下赛后分析,上面这个小游戏究竟有多少个线程呢?我听到有人说“这个很容易就看出来了,一共就3个吗,每个参赛的跑者,都是一个线程”。真的只是表面看到的这样吗?
这个程序一共有5个线程!
不信吗?那听我来说说:第1个线程,就是被大家忽略了,却有非常熟悉的
main。这个是我们java 程序运行时,必定会运行的,也是我们学习java时最早接触的一个线程。第2、3、4个 线程,就是大家说的,那三个赛跑者,每一个都是一个独立的线程。第5个线程,从图上是看不到的,却又是一个非常重要的线程,它甘居幕后,担任着发令,裁决输赢的任务,我们暂且把它叫做“裁判”吧。
整个游戏的过程我们了解了,所包含的线程我们也都分析了,下面的时间就是着手实现的阶段了:
打着MVC的旗号,项目结构成了下面这个样子:
images:中放置着,程序所需要的全部图片
vo:里放着我们的一个实体类 enter:里存放着程序的入口
view:里存放着程序的界面
control里存放着“裁判”类和监听器。
界面部分的编写我就不细说了,就是要继承JFrame来定义我们自己的窗体。顺便说一句,那个跑道是通过画图绘制的背景。别忘了给按钮添加监听器哦!
今天的主题是线程,那么我们就要仔细看看线程的代码了:
java中实现线程的有两种途径,一种是继承Thread类,还有一种是实现Runnable接口。下面的关于 “运动员”、”裁判”的实现,我都统一使用了第二种方法,就是实现Runnable接口。具体代码如下: package saipao.vo; import java.awt.Image; import java.awt.Point; import java.util.Random; import javax.swing.ImageIcon; public class Runners implements Runnable{ private String name; //名称 private Point weiZhi;// 位置x和y的坐标 private ImageIcon imgBig; //大图片 private ImageIcon imgSmall; //小图标 private boolean flag; //是否被下注,初值为false private boolean win;//是否到达了终点 true为到达,false为没到达 private boolean isRun;//是否继续跑 ,true为继续,false为停止 /* * 名称、坐标、图片,小图标是只读的,只有get方法 * */ public boolean isFlag() { } public void setFlag(boolean flag) { } public String getName() { } public Point getWeiZhi() { } public ImageIcon getImgBig() { } public ImageIcon getImgSmall() { return imgSmall; return imgBig; return weiZhi; return name; this.flag = flag; return flag; } public void setWin(boolean win) { } public boolean isRun() { } public void setRun(boolean isRun) { } public Runners(String name,int x,int y,String imageName) { super(); this.name = name; this.weiZhi=new Point(x, y); this.imgBig=new this.isRun = isRun; return isRun; this.win = win; ImageIcon(this.getClass().getResource(\"/images/\"+imageName+\".gif\")); this.imgSmall=new ImageIcon(this.getClass().getResource(\"/images/\"+imageName+\"1.GIF\")); } //退到起点 public void fuWei(){ this.weiZhi.move(0, (int)this.weiZhi.getY()); this.flag=this.win=false; this.isRun=true; this.isRun=true; //默认为继续跑 } //是否押对了 public boolean isWiner(){ } return this.flag&this.win; //重写Runnable接口中的Run方法,实现 x y坐标的改变 } 好了,运动员的代码我们看到了,你发现了Runnable接口中声明了几个方法了吗? 答对了,就一个叫做Run的方法。当线程启动后,就将会执行Run方法中的代码。知道执行完毕退出run方法,此线程就死亡了。
光有运动员,没有裁判怎么行! public void run() { } Random rd=new Random(); //用于控制速度的随机数 while(this.isRun){ } int x=(int)this.weiZhi.getX(); x+=rd.nextInt(10)+1; this.weiZhi.move(x,(int)this.weiZhi.getY()); try { Thread.sleep(100); } catch (InterruptedException e) { } // TODO Auto-generated catch block e.printStackTrace(); package saipao.control; import java.util.Vector; import javax.swing.JOptionPane; import saipao.view.MainFrame; import saipao.vo.Runners; /* * 裁判类,用来确定是否有到达终点的赛跑者 * */ public class CaiPan implements Runnable{ Vector 在和大家说byebye之前,还想请大家思考一下,运动员(Runners)那个类除了通过实现Runnable接口来编写线程程序,还有没有别的方式,使其成为线程?如果有,那么会不会影响我们其他类的代码呢? 立即动手吧!我会一直期待着你的答案哦! 作者:中软卓越天津ETC 因篇幅问题不能全部显示,请点此查看更多更全内容