java多线程——线程通信wait与notify
wait、notify、notifyAll 三个方法均必须在synchronized 下才是使用,而且调用方必须是synchronized 的锁对象,如果是其他对象调用,则会报错
且notify和notifyAll所唤醒的线程是同一个锁对象的等待状态的线程
一个例子
class Patient implements Runnable {
//生病 生病后唤醒医生给病人治病
public synchronized void ill() {
Hospital.patientNumber++;
System.out.println("get cold --->" + Hospital.patientNumber);
notifyAll();
}
@Override
public void run() {
ill();
}
}
class Doctor implements Runnable {
//治疗 如果没有病人就等待 如果有就被唤醒 给人治病
public synchronized void treat() throws InterruptedException {
while (Hospital.patientNumber <= 0) {
wait();
}
Hospital.patientNumber--;
System.out.println("drink more hot water --->" + Hospital.patientNumber);
}
@Override
public void run() {
try {
treat();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Hospital {
public static int patientNumber = 0;
}
public class WaitAndNotifyTest {
public static void main(String[] args) {
Patient patient = new Patient();
Doctor doctor = new Doctor();
for (int i = 0; i < 10; i++) {
new Thread(doctor).start();
}
for (int i = 0; i < 10; i++) {
new Thread(patient).start();
}
}
}
结果是

原因就是两个函数的锁对象不同,所以病人生病并不能唤醒医生(其实,锁对象不同 对于Hospital.patientNumber这个变量的修改并没有有效的同步保护,只是Doctor和Doctor线程、Patient和Patient线程之间不能同时访问,因为是同一个锁,但是Doctor和Patient线程之间还是有可能同时访问,因为他们的锁不同)
修改代码如下:
class Patient implements Runnable {
//生病 生病后唤醒医生给病人治病
public void ill() {
synchronized (Hospital.class) {//注意锁的变化
Hospital.patientNumber++;
System.out.println("get cold --->" + Hospital.patientNumber);
Hospital.class.notifyAll();//注意调用对象的变化
}
}
@Override
public void run() {
ill();
}
}
class Doctor implements Runnable {
//治疗 如果没有病人就等待 如果有就被唤醒 给人治病
public void treat() {
synchronized (Hospital.class) {//注意锁的变化
while (Hospital.patientNumber <= 0) {
try {
Hospital.class.wait();//注意调用对象的变化
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Hospital.patientNumber--;
System.out.println("drink more hot water --->" + Hospital.patientNumber);
}
}
@Override
public void run() {
treat();
}
}
class Hospital {
public static int patientNumber = 0;
}
public class WaitAndNotifyTest {
public static void main(String[] args) {
Patient patient = new Patient();
Doctor doctor = new Doctor();
for (int i = 0; i < 10; i++) {
new Thread(doctor).start();
}
for (int i = 0; i < 10; i++) {
new Thread(patient).start();
}
}
}
结果如下:

如果遇到错误java.lang.IllegalMonitorStateException:说明synchronized的锁对象和调用wait还有notify的对象不一致(因为Wait()需要释放锁,如果调用的对象不是这个锁对象就无法释放掉这个锁)

浙公网安备 33010602011771号