这里需要强调的是,wait方法和notify方法,并不是Thread线程上的方法,它们是Object上的方法。
因为所有的Object都可以被用来作为同步对象,所以准确的讲,wait和notify是同步对象上的方法。
wait()的意思是: 让占用了这个同步对象的线程,临时释放当前的占用,并且等待。 所以调用wait是有前提条件的,一定是在synchronized块里,否则就会出错。
notify() 的意思是,通知一个等待在这个同步对象上的线程,你可以苏醒过来了,有机会重新占用当前对象了。
notifyAll() 的意思是,通知所有的等待在这个同步对象上的线程,你们可以苏醒过来了,有机会重新占用当前对象了。
package thread;
/**
*
* @title 线程的交互(通信)
* @description 通过线程间的通信,完成对英雄同时加血 、减血的操作。要求 一边加血一遍减血,减血为1时,加血。
* @author xiaox
* @date 2018年5月28日
*/
public class InteractionThread {
public static class Hero {
public String name;
public float hp;
public int damage;
public void recover() {
hp = hp + 1;
}
public void hurt() {
hp = hp - 1;
}
}
public static void main(String[] args) {
final Hero gareen = new Hero();
gareen.name = "盖伦";
gareen.hp = 100;
autoAddReduce(gareen);
}
public static void autoAddReduce(Hero hero) {
// 减血线程
Thread reduceThread = new Thread(new Runnable() {
@Override
public void run() {
// 一直减血到1,然后加血到100
System.out.println("进入线程A");
while (true) {
System.out.println("A线程进入循环");
synchronized (hero) {
System.out.println("A线程进入hero同步块");
hero.hurt();
System.out.println("A线程正在减血: " + hero.hp);
if (hero.hp == 1) {
try {
System.out.println("A线程调用对象hero.wiat()方法,该线程进入等待池");
hero.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
System.out.println("A线程退出hero同步块");
try {
System.out.println("A线程睡眠等待10毫秒");
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
reduceThread.start();
Thread addThread = new Thread(new Runnable() {
@Override
public void run() {
// 一直加血到100,然后减血到1
System.out.println("进入线程B");
while (true) {
System.out.println("进入B线程循环");
synchronized (hero) {
System.out.println("进入B线程同步块");
hero.recover();
System.out.println("B线程正在加血: " + hero.hp);
System.out.println("B线程调用hero.notify()方法,唤醒一个等待池中的线程");
hero.notify();
}
System.out.println("B线程退出hero同步块");
try {
System.out.println("B线程调睡眠等待100毫秒");
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
addThread.start();
}
}