这个实际上是线程通信的问题,你的这个代码是在printer1线程和printer2之间进行相互唤醒的通信。这时候必须保证两个同步代码块使用同一把锁,而楼主的两个代码块一个使用的是obj锁,一个用的是this锁,也就是说这两个线程实际上并未同步,还在各自执行自己的run方法内容。
另外就需要了解notify,natifyAll,wait这三个方法了
这三个方法使用时,当前线程必须是当前对象锁资源的持有者,否则就会报IllegalMonitorStateException这个错误。由于两个代码块持有的锁资源不同,为实现同步,就报错了。
如果了解IllegalMonitorStateException 这个错误在上面时候下出现就容易解决了,
这个异常会在三种情况下抛出:1>当前线程不含有当前对象的锁资源的时候,调用wait()方法;2>当前线程不含有当前对象的锁资源的时候,调用notify()方法。3>当前线程不含有当前对象的锁资源的时候,调用notifyAll()方法。如果楼主不想用同步函数,而要用同步代码块的话,用下面这种写法就不会报错了。
class Exercise { public static void main(String args[]) { final Print p=new Print(); new Thread() { public void run() {
for(;;) p.printer1();
} }.start();
new Thread() { public void run() {
for(;;) p.printer2();
} }.start(); } } class Print { private int flag=1; private Object obj = new Object(); public void printer1(){ synchronized(obj){ //用 synchronized代码块就会报异常 if(flag==2) try{ obj.wait();//注意蓝色的部分必须加上obj.否则还会报错,这时候锁变成obj而不是this了,如果你省略那默认还是this,但实际上用的是obj锁而不是this,所以必须写上obj. }catch(Exception e){ e.printStackTrace(); } System.out.println("黑"); System.out.println("马"); System.out.println("最"); System.out.println("牛");
obj.notify(); flag=2;
} }
public void printer2(){ //为什么用 synchronized方法就不报异常呢 synchronized(obj){ if(flag==1) try{ obj. wait(); }catch(Exception e){ e.printStackTrace(); } System.out.println("I"); System.out.println("L"); System.out.println("O"); System.out.println("V"); System.out.println("E"); System.out.println("Y"); System.out.println("O"); System.out.println("U");
obj.notify(); flag=1; } } } |