龟兔赛跑之Java多线程通讯初识
程序员文章站
2022-05-02 10:58:07
...
注:这是第一次写自己的博客,试试效果怎么样
一,前言
龟兔赛跑这个寓言故事,是一个经典的多线程并发的案例。通过这个案例的学习,可以对Java中线程之间通讯有一个初步的认识。
二,场景假设
1.跑道长度为20米;
2.乌龟和兔子同时出发,乌龟的速度为0.1m/s,乌龟不休息;兔子的速度为0.5m/s,兔子每跑2米就休息一次,每次休息时间为2秒;
3.当有一个动物到达终点时,获胜者宣布比赛结束,需要告知失败者不用继续跑了。
三、代码解读
1.抽取公共父类Animal
package com.netops.demo3;
/**
* 场景假设(龟兔赛跑问题):
* 跑道长度20米;
* 兔子速度0.5米/秒,每跑2米休息1秒;乌龟速度0.1米/秒,不休息;
*当一个动物到达终点,宣布比赛结束并告知另外一个动物不用再跑了。
*/
//将龟兔抽取父类--动物类
public abstract class Animal extends Thread{
//距离跑道终点的长度,初始值即跑道长度为20米
public double distance = 20;
//跑步策略,每个动物有各自不同的实现
public abstract void running();
@Override
public void run() {
while(distance > 0){
running();
}
}
//当获胜者出现,宣布比赛结束
public interface IsWinner{
void gameOver();
}
public IsWinner isWinner;
}
2.两个实体类
package com.netops.demo3;
public class Rabbit extends Animal {
//给线程命名
public Rabbit(String name){
setName(name);
}
@Override
public void running() {
double speed = 0.5;//兔子跑步速度
distance -= speed;//距终点距离
if(distance<=0){
speed = 0;
System.out.println(getName()+ "获得了胜利");
if(isWinner != null){
isWinner.gameOver();//获胜者宣布比赛结束
}
}
//speed为0表示兔子在休息,为0.5表示兔子正在奔跑
System.out.println(getName() + "此时速度为:" + speed + ",距离终点还有" + distance + "米" );
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//每2米休息一次
if(distance %2 == 0){
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.netops.demo3;
public class Tortoise extends Animal {
//给线程命名
public Tortoise(String name){
setName(name);
}
@Override
public void running() {
double speed = 0.1;//乌龟跑步速度
distance -= speed;//距终点距离
if(distance <= 0){
speed = 0;
System.out.println(getName()+ "获得了胜利");
if(isWinner != null){
isWinner.gameOver();//获胜者宣布比赛结束
}
}
//speed为0表示乌龟已经到了终点,为0.1表示乌龟正在奔跑
System.out.println(getName() + "此时速度为:" + speed + ",距离终点还有" + (int)distance + "米" );
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3.实现回调接口的类
package com.netops.demo3;
/**
* 通过这个实现了回调接口的类的gameOver()方法,
* 将‘获胜者已经出现’的信息告知失败者
* 失败者采取的行动‘调用方法stop()’即停止线程运行。
* /
public class LetAnotherStop implements IsWinner{
Animal animal;
public LetAnotherStop(Animal animal){
this.animal = animal;
}
@Override
public void gamerOver() {
// 线程停止
animal.stop();
}
}
4.测试类
package com.netops.demo3;
/**
* 龟兔赛跑的测试类
*/
public class Main {
public static void main(String[] args) {
Animal rabbit = new Rabbit("兔子");
Animal tortoise = new Tortoise("乌龟");
/*
下面这四句话,实现了线程之间的通讯,
如果兔子先到达终点,则告知乌龟不用再跑了;(即若Thread_rabbit先执行完,则告知Thread_tortoise不用再执行了)
反之亦然。
*/
LetAnotherStop letTortoiseStop = new LetAnotherStop(tortoise);
rabbit.isWinner = letTortoiseStop;
LetAnotherStop letRabbitStop = new LetAnotherStop(rabbit);
tortoise.isWinner = letRabbitStop;
rabbit.start();
tortoise.start();
}
}
5.控制台结果展示
5.总结
在实体类Rabbit,Tortoise类中均有一段代码<< sleep(100); >>,目的是为了让结果在控制台上的展示更接近实际效果。两个线程周期性地阻塞0.1秒,可以理解为:现实中每过1秒,记录Rabbit和Tortoise的状态(速度、位置),并将结果打印在控制台上。于是就有了如上图所示的结果展示。