本文已参与「新人创作礼」活动,一起开启掘金创作之路。
首先是需求:
- 用两个线程分别模拟乌龟和兔子奔跑。兔子和乌龟的速度不同。
- 两个线程共同跑完总长1000米。
- 同一时间只能有一个在跑,另一个处于休息状态。(兔子和乌龟严格轮流交替跑)
- 当总长度跑完以后,两个线程结束。
- 当两个线程都结束后,打印"到达终点"。
- 分别输出乌龟和兔子奔跑的距离。
分析:
1.首先需要确定使用什么方式创建线程,这里我们选用实现Runnable接口方式进行创建线程,因为这种方式的好处很多。具体的可以参考这篇文章,可以让你对创建线程的三种方式有一定认识。也有助于了解这次代码的写法。
Evader1997:创建线程的三种方式及Thread源码解析5 赞同 · 4 评论文章
2.读完需求后,我们知道必须有三个变量:一个用于存储总距离1000米,一个用于存储乌龟跑的距离,一个用于存储兔子跑的距离。
3.是两个线程在抢一个资源,并且是严格的交替跑,所以我的想法是将公共资源1000米单独定义在一个Race类中,通过在Rannable实现类中创建构造方法,将Race类对象当做构造方法的参数。在运行类中,创建方法时传入同一个Race对象,这样就实现了两个线程争抢同一个资源。
4.强制交替跑,这里用到了notify方法跟wait方法。
专栏定位是给初学者一些练手的案例,希望已经有经验的读者轻喷,觉得案例简单的可以看看上面这篇文章。
一共包括四个类,一个乌龟类,一个兔子类,一个赛跑(race类),一个运行类。
Race类:该类作用是提供公共资源1000米,提供pao方法用于表示兔子,乌龟跑的距离。
public class Race {
// 定义总距离1000米
private int juli = 1000;
// 定义变量存储乌龟跑的距离
private int guiju;
// 定义变量存储兔子跑的距离
private int tuju;
public synchronized void pao() {
if (juli > 0) {
if (Thread.currentThread().getName().equals("乌龟")) {
try {
juli -= 5;
guiju += 5;
System.out.println("乌龟跑了5米,总路程还剩" + juli + "米");
// 这里需要注意先唤醒在等待
notifyAll();
wait();
if (juli <= 0) {
System.out.println("接力完成!兔子跑了" + tuju + "米,乌龟跑了" + guiju + "米");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (Thread.currentThread().getName().equals("兔子")) {
try {
if (juli < 10) {
juli -= 5;
tuju += 5;
// 这边运行发现结果出现剩余-5米,所以才有了这行判断
System.out.println("兔子跑了剩下的5米,总路程还剩" + juli + "米");
notifyAll();
wait();
} else {
juli -= 10;
tuju += 10;
System.out.println("兔子跑了10米,总路程还剩" + juli + "米");
notifyAll();
wait();
}
if (juli <= 0) {
System.out.println("接力完成!兔子跑了" + tuju + "米,乌龟跑了" + guiju + "米");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
乌龟类:该类的作用是提供一个带参构造,参数是Race类型的参数,这样是为了实现了两个线程争抢一个资源的需求。另外受Thread源码的启发,在乌龟类中我的run方法是不做事的,做事的是Race类中pao()方法。
public class WuGui implements Runnable {
private Race race;
public WuGui(Race race) {
this.race = race;
}
@Override
public void run() {
while (true) {
race.pao();
}
}
}
兔子类:兔子类跟乌龟类是一样的,同样将创建对象时传入了一个Race类型的对象。
public class TuZi implements Runnable {
private Race race;
public TuZi(Race race) {
this.race = race;
}
@Override
public void run() {
while (true) {
race.pao();
}
}
}
运行主类:该类的作用是创建一个公共资源对象race,创建龟兔两个线程都传入race对象,让两个线程“跑的是统一段路”
public class RaceDemo {
public static void main(String[] args) throws Exception {
Race race = new Race();
WuGui wg = new WuGui(race);
TuZi tz = new TuZi(race);
Thread w = new Thread(wg, "乌龟");
Thread t = new Thread(tz, "兔子");
w.start();
t.start();
}
}
运行结果:如果你运行后的结果是这,恭喜你完成了这个练习,撒个花。