-
线程理解
假设在一台电脑上会有很多个应用,你可以同时开启多个应用,这个被称作进程 一台电脑可以同时有多个进程运行,每个进程里面会有多个线程同时运行,举个例子,你打开一个视频播放软件,你可以同时下载视频,也同时在看着视频,这就是在一个进程里面有两个线程,线程的通俗理解就是可以我可以在看电视的同时也在吃着饭,互相不影响都在进行着。 -
利用飞机大战游戏来运行多线程
-代码用来实现飞机大战的窗口界面
public void init() {
//飞机大战窗口
this.setTitle("飞机大战");
this.getContentPane().setBackground(Color.GRAY);
this.setSize(1200, 1000);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
FlowLayout flowLayout = new FlowLayout();
this.setLayout(flowLayout);
//JButton ju = new JButton("暂停");
//ju.setBackground(Color.PINK);
//this.add(ju);
this.setVisible(true);
}
- 给窗口添加鼠标监听器
//鼠标监听器在鼠标释放的瞬间从我方飞机开始发射我方子弹
mouse mu = new mouse(aa,g);
this.addMouseListener(mu);
//为鼠标移动监听器,目的是鼠标移动到哪,我方飞机就移动到哪里
mouselisen mu2 = new mouselisen(ball);
this.addMouseListener(mu2);
//这里获取当前窗体的画笔
Graphics g = this.getGraphics();
//定义一个队列属性,用来存放窗体上可能出现的一切物体,<imove>为队列的泛型,imove为一个接口
java.util.ArrayList<imove> aa = new ArrayList<imove>();
ArrayList<goalair> bb = new ArrayList<goalair>();
- imove接口的定义
public interface imove {
//名字
public void setName(String name);
public String getName();
//当前坐标的获取
public int getX();
public int getY();
//当前坐标的设置
public void setX(int x);
public void setY(int y);
//画出自己
public void drawMe();
//自己的移动
public void move();
}
- 因为窗体里面的对象都有自己的运动,因此需要在线程里面完成
public class BallThread extends Thread {
//因为需要在线程里面对对象进行绘制,因此定义画笔graphics
private Graphics graphics;
//在线程里面要从队列里面取出存储的对象,因此定义队列
private ArrayList<imove> aa;
//因为继承了Thread类,在里面对线程方法run重写
public void run() {
while(true) {
//方法体 完成各个对象的移动与绘制
}
}
}
//构造方法将窗体里面的画笔和队列传过来,在线程里面进行操作
public BallThread(Graphics graphics,ArrayList<imove> aa){
this.graphics = graphics;
this.aa = aa;
//启动线程,线程启动后会不停循环,不会停止下来,各个线程会不断的执行自己接下来的操作
BallThread ball = new BallThread(g,aa);
ball.start();
- 游戏一开始我方飞机会出现在窗体上
Random ran = new Random();
airCraft air = new airCraft(0,500,g,"我机");
aa.add(air);
//飞机的类
//在里面根据不同的名字对飞机分类为我方飞机还是敌方飞机,在对其进行绘制和移动
public class airCraft implements imove {
private int x,y;
Graphics gg;
private String name ;
public airCraft(int x,int y,Graphics gg,String name) {
// TODO Auto-generated constructor stub
this.gg = gg;
this.x = x;
this.y = y;
this.name = name;
}
public void drawMe() {
if(name.equals("我机")) {
gg.setColor(Color.GRAY);
gg.fillRect(x, y, 40, 40);
}
if(name.equals("敌机")) {
gg.setColor(Color.ORANGE);
//System.out.println(252528);
gg.fillRect(x, y, 40,60);
//gg.f
}
}
@Override
//飞机的移动
public void move() {
if(name.equals("敌机")) {
x -= 7;
}
if(x <0 || x > 1200) {
name = "消失";
}
}
}
- 子弹类与上面飞机类相同
public class bullet implements imove{
Graphics gg;
private int x,y;
private String name;
public bullet(Graphics gg,int x, int y,String name) {
this.x =x;
this.y = y;
this.gg = gg;
this.name = name;
}
}
- 由于设计敌机出现是随机的,因此对于敌机的产生也利用一个线程产生对象,添加到队列里面去
//产生敌机的线程
public void run() {
while(true) { 、
//随意从窗体最左边产生不同的敌机
Random ran = new Random();
x = 1100;//坐标x一直为窗体最左边
y = ran.nextInt(500);
airCraft goal = new airCraft(x, y,gg, "敌机");
aa.add(goal);
try {
Thread.sleep(ran.nextInt(1200));
}catch(Exception e) {}
for(int i = 1;i < aa.size();i++) {
//遍历队列如果发现产生的敌机,获取敌机的位置并从此位置产生敌方子弹并添加到队列当中去,在ballThread线程里面去画、移动
imove mm = aa.get(i);
if(mm.getName().equals("敌机")) {
bullet bu = new bullet(gg, mm.getX()-10, mm.getY(), "敌方子弹");
aa.add(bu);
}
}
}
}
//敌机不断产生线程的启动
AttackAir at = new AttackAir(g,aa);
at.start();
-
最后结果显示
-
总结
通过一个队列将所有出现在窗体上的对象保存起来,在线程里面不断地读取出来队列里面保存的对象,在重写的run方法里面进行相应各个类的方法的调用实现对象的绘制与移动,线程启动run方法会不断执行,将每一个队列里面的对象都会取出来根据相应的判断执行一次。