预想:
盖伦减血1点,现在盖伦的hp是: 99.0
盖伦减血1点,现在盖伦的hp是: 97.0
盖伦减血1点,现在盖伦的hp是: 98.0
盖伦的血恢复1点,现在盖伦的hp是:99.0
盖伦的血恢复1点,现在盖伦的hp是:100.0
盖伦的血已满!
结果:
盖伦减血1点,现在盖伦的hp是: 99.0
盖伦减血1点,现在盖伦的hp是: 97.0
盖伦减血1点,现在盖伦的hp是: 98.0
盖伦的血恢复1点,现在盖伦的hp是:99.0
盖伦的血恢复1点,现在盖伦的hp是:100.0
盖伦的血恢复1点,现在盖伦的hp是:98.0
这两个线程组之间有什么匹配问题?
代码:
TestHero.java
public class TestHero {
public static void main(String[] args) {
Hero gareen = new Hero("盖伦", 100, 10);
int N = 3;
Thread[] hurtThreads = new Thread[N];
Thread[] coverThreads = new Thread[N];
for (int i = 0; i < N; i++) {
Thread t1 = new Thread(() -> {
gareen.hurt();
System.out.println("盖伦减血1点,现在盖伦的hp是: " + gareen.hp);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
hurtThreads[i] = t1;
}
for(Thread t : hurtThreads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j = 0; j < N; j++){
Thread t2 = new Thread(() -> {
gareen.recover();
System.out.println("盖伦的血恢复1点,现在盖伦的hp是:"+ gareen.hp);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t2.start();
coverThreads[j] = t2;
}
}
}
Hero.java
import java.io.Serializable;
public class Hero{
public String name;
public float hp;
public int damage;
public Hero(){
}
public Hero(String name,float hp,int damage){
this.name = name;
this.hp = hp;
this.damage = damage;
}
// 伤害和恢复这两个线程同时只能有一个线程在执行
public synchronized void hurt(){
if(hp == 1){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.hp -= 1;
this.notify();
}
public synchronized void recover(){
if(hp == 1000){
System.out.println(this.name + "的血已满!");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.hp += 1;
this.notify();
}
public void attackHero(Hero h) {
try {
//为了表示攻击需要时间,每次攻击暂停1000毫秒
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
h.hp-=damage;
System.out.format("%s 正在攻击 %s, %s的血变成了 %.0f%n",name,h.name,h.name,h.hp);
if(h.isDead())
System.out.println(h.name +"死了!");
}
public boolean isDead() {
return 0>=hp?true:false;
}
}
结果没问题呀,在执行recover的三个线程之前,由于join方法,可以保证当时盖伦的血量是97,所以recover的三个线程不就是98,99,100,由于三个线程不是顺序执行的,所以
盖伦的血恢复1点,现在盖伦的hp是:99.0
盖伦的血恢复1点,现在盖伦的hp是:100.0
盖伦的血恢复1点,现在盖伦的hp是:98.0
这三句话以任何顺序输出都有可能呀。
recover() 中,1000 是什么意思?
– 快乐的凡人721 3年前@快乐的凡人721: 盖伦初始Hp是100,原本我要改成1000的,recover的1000意思是加血到了1000的时候就会中止线程,等到被减血了再加血,不过这不影响阅读
– 另一种开始 3年前