synchronized 与IllegalMonitorStateException异常

来看一个面试题目

在子线程中执行一段代码10次,然后在主线程中执行代码50次,然后再在子线程中执行代码10次,然后是主线程....这样循环50次,应该如何实现

这个题目考验的是线程的互斥和通信,互斥就是加一个锁,通信就是设置一个共享的值,我以为很简单就用下面的代码实现

<pre name="code" class="java">package day20150802;

import org.junit.Test;

public class CopyOfMainAndSubThreadTest2 {
	private final static Object Monitor = new Object();
	private static boolean first = false;
	private static boolean control = true;
	@Test
	public  void main()  {
			final Run run = new Run();
			new Thread(new Runnable() {
			public void run() {
				for(int sub = 0;sub<50;sub++){
					run.sub(sub);
				}
			}
		} ).start();
		for(int sub = 0;sub<50;sub++){
			run.main(sub);
		}
	}
}
class Run{
	private final Object Monitor = new Object();
	private boolean control =true;
	
	public  void main(int j){
		synchronized(this.Monitor){
		while(!control){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
			for(int i = 0;i<50;i++)
			System.out.println("main "+(j+1)+"--"+(i+1));
			control=false;
			
	}
		notify();
	}
	public  void sub(int sub) {
		synchronized(this.Monitor){
		while(control){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				System.out.println(e);
				e.printStackTrace();
			}
		}
		for(int i = 0;i<10;i++){
			System.out.println("sub "+(sub+1)+"--"+(i+1));
		}
		control=true;
	}
		this.notify();
	}
}

 

执行结果:

[Console output redirected to file:C:\Myeclipse\MyEclipse 10\OutPutTest.JavaTestOutTxt]
main 1--1
main 1--2
main 1--3
main 1--4
main 1--5
main 1--6
main 1--7
main 1--8
main 1--9
main 1--10
main 1--11
main 1--12
main 1--13
main 1--14
main 1--15
main 1--16
main 1--17
main 1--18
main 1--19
main 1--20
main 1--21
main 1--22
main 1--23
main 1--24
main 1--25
main 1--26
main 1--27
main 1--28
main 1--29
main 1--30
main 1--31
main 1--32
main 1--33
main 1--34
main 1--35
main 1--36
main 1--37
main 1--38
main 1--39
main 1--40
main 1--41
main 1--42
main 1--43
main 1--44
main 1--45
main 1--46
main 1--47
main 1--48
main 1--49
main 1--50
sub 1--1
sub 1--2
sub 1--3
sub 1--4
sub 1--5
sub 1--6
sub 1--7
sub 1--8
sub 1--9
sub 1--10
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at day20150802.Run.sub(CopyOfMainAndSubThreadTest2.java:61)
at day20150802.CopyOfMainAndSubThreadTest2$1.run(CopyOfMainAndSubThreadTest2.java:15)
at java.lang.Thread.run(Thread.java:619)

而把 synchronized 锁加到 方法上面就可以运行了,代码如下


<pre name="code" class="java">package day20150802;

import org.junit.Test;

public class CopyOfMainAndSubThreadTest2 {
	private final static Object Monitor = new Object();
	private static boolean first = false;
	private static boolean control = true;
	@Test
	public  void main()  {
			final Run run = new Run();
			new Thread(new Runnable() {
			public void run() {
				for(int sub = 0;sub<50;sub++){
					run.sub(sub);
				}
			}
		} ).start();
		for(int sub = 0;sub<50;sub++){
			run.main(sub);
		}
	}
}
class Run{
	private final Object Monitor = new Object();
	private boolean control =true;
	
	public synchronized  void main(int j){
		
		while(!control){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
			for(int i = 0;i<50;i++)
			System.out.println("main "+(j+1)+"--"+(i+1));
			control=false;
			this.notifyAll();
	}
	public synchronized void sub(int sub) {
		while(control){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				System.out.println(e);
				e.printStackTrace();
			}
		}
		for(int i = 0;i<10;i++){
			System.out.println("sub "+(sub+1)+"--"+(i+1));
		}
		control=true;
		this.notifyAll();
	}
}

 

这是为什么??

我看查询完资料后发现,synchronized是获取对象内部的锁,而我使用同步代码块的时候,获取的是Monitor的内部锁,而不是这个类的内部锁,所以,this.notify();改为this.Monitor.notify()就可以了

package day20150802;

import org.junit.Test;

public class CopyOfMainAndSubThreadTest2 {
	private final static Object Monitor = new Object();
	private static boolean first = false;
	private static boolean control = true;
	@Test
	public  void main()  {
			final Run run = new Run();
			new Thread(new Runnable() {
			public void run() {
				for(int sub = 0;sub<50;sub++){
					run.sub(sub);
				}
			}
		} ).start();
		for(int sub = 0;sub<50;sub++){
			run.main(sub);
		}
	}
}
class Run{
	private final Object Monitor = new Object();
	private boolean control =true;
	
	public  void main(int j){
		synchronized(this.Monitor){
		while(!control){
			try {
				this.Monitor.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
			for(int i = 0;i<50;i++)
			System.out.println("main "+(j+1)+"--"+(i+1));
			control=false;
			this.Monitor.notifyAll();
	}
		
	}
	public  void sub(int sub) {
		synchronized(this.Monitor){
		while(control){
			try {
				this.Monitor.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				System.out.println(e);
				e.printStackTrace();
			}
		}
		for(int i = 0;i<10;i++){
			System.out.println("sub "+(sub+1)+"--"+(i+1));
		}
		control=true;
		this.Monitor.notifyAll();
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值