如何使用线程

线程:

 

   1.概念:线程就是一个独立的运行单位,其内部数据和状态都是完全独立的。简单的说,就是一旦触发,就由它自己去运行,不用再管,由系统自行去根据代码执行,所以一旦运行就马上返回,不用等待。这样可以实现多个线程同时执行。

   2.实现线程的3种方式:

1.继承Thread类实现线程

public class Bullet extends Thread{
			// 运动的速度
			private static int speed = 2;
			// 传入画布
			private Graphics g;
			// 当前子弹的名字
			String name;
			// 传入坦克的坐标值
			int x;
			int y;

			//调用启动函数
			public void run() {
			shot();
			}
			public void shot{
				"这里写入子弹运动的过程"
			}
		}
 

这里实现了一个子弹的运行过程,只要在shot方法中画出子弹运动的过程就可以了。这样其实就实现了一个简单的线程,当我们直接调用bullet的strat方法就可以了,如

Bullet bullet = new Bullet();
 		bullet.strat();
 

这里调用的是strat方法,可是由于这是一个线程对象,所以系统自动调用run()方法的东西,并立即返回。

这里问题就来了,我们为什么非要调strat去启动run方法呢,为什么不直接调用shot方法呢?呵呵,其实可以去试一试的,因为我们当时是设计有坦克的,这只是其中的子弹类而已,如果直接调用shot方法的话,需要等待,也就是说,在第一颗子弹结束之前,坦克是不能动的,并且不能发射第二颗子弹,明白了吗。这就是线程的作用,可以并行。在子弹运行的同时,坦克也可以运行,这才是符合逻辑。子弹作为一个单独的线程去运行。

注意:一定要记得重写run()方法。

2.实现Runnable的方法实现线程

1.前面写了很多来告诉为什么要使用线程,有什么好处,并且也说了通过继承的方法实现线程启动,这里介绍另一种常用方法,通过继承Runnable的方法实现线程的启动。还是以子弹作为研究对象,如:

public class BulletRunnable implement Runnable {
			//传入的坦克对象
			Tank tank;
			//重写构造方法
			public BulletRunnable(Tank tank, Graphics g) {
				this.g = g;
				this.tank = tank;
			}
			//调用启动函数
			public void run() {
				shot();
			}
			public void shot(){
				"这里画出子弹运动的过程"
			}
		}
 

这里创建了一个类,该类实现了Runnable接口,所以就必须实现它的抽象方法run(),其实前面的Thread也是实现的Runnable接口的,所以可以通过继承Thread类来实现线程的启动,现在我们自己写了一个类实现了Runnable,所以也可以通过这个类来启动线程。

所以只需要通过我们实现了接口的类创建一个线程,并调用线程即可。如:

BulletRunnable tr = new BulletRunnable(tank, g);
		Thread thread = new Thread(tr);
		// 线程启动
		thread.start();
 

这样一样可以启动线程。

3.通过匿名内部类,实现接口Runnable

      

 /**
	 	* 启动一个线程
	 	*/
		public void stratBullet(){
			//通过匿名内部类实现接口
			Runnable rab = new Runnable(){
				public void run(){
					“画出子弹运行的过程”
				}	
			}
			//启动线程
			Thread thread = new Thread(rab);
			thread.strat();	
		}
 

这样也实现了一颗子弹的发射,由于篇幅缘故,没有写出具体画出子弹的方法,因为这是个很复杂的问题,要考虑的诸如碰到坦克和墙等等的情况,所以代码非常复杂,没有把具体情况写出来。

   3.sleep方法的运用。

1.其实sleep方法的运用是比较重要的,因为一个线程在执行时,会一直占用资源,这是不合理的,因为一般情况下,比如一个坦克,在它未被消灭之前,会一直执行run方法,因此,在它在打死之前,其实一直都在调用run方法。如果不去处理这种情况,那么系统的cpu占用会达到100%,这是绝对不合理的,就像程序陷入死循环一样的效果。所以我们需要调用Thread的sleep方法。它可以让程序休眠一段时间,之后继续运行。

2.写出一段子弹类的,shot方法具体代码;

while (true) {// 开始发射子弹
			// 先画一个子弹
			g.drawImage(image, x, y, WideB, HighB, null);
			try {
				this.sleep(10);// 线程休眠
				g.setColor(Color.BLACK);
				g.fillRect(x, y, WideB, HighB);// 画矩形把原先图片盖住

				// 判断坦克方向,改变相应运动坐标
				if (direction.equals("Right")) {
					x += speed;
				}
				if (direction.equals("Left")) {
					x -= speed;
				}
				if (direction.equals("Up")) {
					y -= speed;
				}
				if (direction.equals("Down")) {
					y += speed;
				}
				// 画出新位置,走下一步
				g.drawImage(image, x, y, WideB, HighB, null);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			// 判断是否到边界,是跳出循环
			if (x > 885 || x < -5|| y > 580|| y < -5) {
				tank.countBomb++;
				System.out.println(tank.countBomb);
				break;
			}
		}
 

可以看出,其实在子弹出去边界之前,一直是在以死循环的方式不断执行,如果不让程序休眠的话,就会非常快的执行完成,我们根本看不到子弹飞出的效果,也就是说子弹的运行速度是由子弹的休眠时间和速度一起影响的。只是子弹而已所以影响不太大,试想一下,如果一个坦克没有休眠时间是多么难看堪的事情,所以休眠,对于线程来说,是很重要的。

休眠时间以毫秒计算,如果参数是1000,则会休眠一秒。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值