线程之间通讯--java.lang.IllegalMonitorStateException

在写多线程之间通讯的例子--生产者跟消费者时,我用到了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();
			}
			
		}
	}
}


使用synchronized同步代码块解决同步问题,这样就没有之前的异常了。

总结:

      wait与notify在使用的时候必须要保证线程同步。

以上是个人见解,如有不足之处,希望各位指正,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值