来看一个面试题目
在子线程中执行一段代码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();
}
}
}