在写多线程之间通讯的例子--生产者跟消费者时,我用到了wait跟notify,结果在运行时报了java.lang.IllegalMonitorStateException异常,查了一下,这个异常叫做违法的监控状态异常。官方的解释是当一个线程试图等待一个自己并不拥有的对象的监控器或者通知其他线程等待该对象的监控器时抛出的异常。这个解释有点绕,我用代码来说明:以下是出错的代码
public class ThreadCommunicate {
public static void main(String[] args) {
Res res = new Res();
InputThread input = new InputThread(res);
OutThread out = new OutThread(res);
input.start();
out.start();
}
}
class Res {
public String name;
public String sex;
public boolean flag;//flag为true,表示已经生产了,还没有消费
}
class InputThread extends Thread{
private Res res;
public int count = 0;
public InputThread(Res res) {
this.res = res;
}
@Override
public void run() {
while(true){
if(res.flag){
try {
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(count == 0){
res.name = "小红";
res.sex = "女";
} else {
res.name = "boss";
res.sex = "男";
}
count = (count + 1)%2;
res.flag = true;
res.notify();
}
}
}
class OutThread extends Thread{
private Res res;
public OutThread(Res res) {
this.res = res;
}
@Override
public void run() {
while(true){
if(!res.flag){
try {
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(res.name + ":" + res.sex);
res.flag = false;
res.notify();
}
}
}
这段代码有两个线程input与out同时操作同一个对象res,存在线程同步问题,但我并没有解决这个问题,同时我使用了wait跟notify,在线程不同步的时候,就会出现input线程在执行完res.notify()之后,进入到if判断之后、执行res.wait()之前就交出了cpu时间片给out执行,out执行完res.notify()之后进入if中执行res.wait()等待,之后交出cpu时间片给input,然后input也执行了res.wait(),产生了官方所描述的冲突。当然究其主要原因还是因为我没有解决这两个线程的同步问题,以下是改进后的方案:
public class ThreadCommunicate {
public static void main(String[] args) {
Res res = new Res();
InputThread input = new InputThread(res);
OutThread out = new OutThread(res);
input.start();
out.start();
}
}
class Res {
public String name;
public String sex;
public boolean flag;//flag为true,表示已经生产了,还没有消费
}
class InputThread extends Thread{
private Res res;
public int count = 0;
public InputThread(Res res) {
this.res = res;
}
@Override
public void run() {
while(true){
synchronized (res) {
if(res.flag){
try {
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(count == 0){
res.name = "小红";
res.sex = "女";
} else {
res.name = "boss";
res.sex = "男";
}
count = (count + 1)%2;
res.flag = true;
res.notify();
}
}
}
}
class OutThread extends Thread{
private Res res;
public OutThread(Res res) {
this.res = res;
}
@Override
public void run() {
while(true){
synchronized (res) {
if(!res.flag){
try {
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(res.name + ":" + res.sex);
res.flag = false;
res.notify();
}
}
}
}
总结:
wait与notify在使用的时候必须要保证线程同步。
以上是个人见解,如有不足之处,希望各位指正,谢谢!