都不想有错误,但一不小心就犯了
-------------------15/4/17 by codeZhu -------------- java.lang.IllegalMonitorStateException-------------------------------------------------
下午写ReentrantLock的中断,本以为可以顺利的写出来,结果希望越大失望越大,写完一运行,给我哗啦的来了个java.lang.IllegalMonitorStateException,这个错误以前
也见过,相信大家都还记得是在wait()与notify()中。对于这个错误有句话说的很好 “当前的线程不是此对象监视器的所有者”。通俗一点就是不是你的你还拿过来瞎用,程序和人一样
也有脾气,想想你自己是不是也不喜欢别人瞎用你的东西,瞎用了你会发脾气,程序就会报错,这个错误就是IllegalMonitorStateException。
既然有了错误就来找找是在哪里啦。但感觉今天诸事不顺,就是没找到,我把错误的代码贴出来看看。
1 public class ReenTrantLockTest { 2 //reentrantLock锁 3 ReentrantLock lock = new ReentrantLock(); 4 public static void main(String[] args) { 5 ReenTrantLockTest test = new ReenTrantLockTest(); 6 //启动线程1执行任务 7 test.new MyThread1().start(); 8 //再启动线程2去执行,此时线程2会一直等待锁 9 final Thread thread2 = test.new MyThread2(); 10 thread2.start(); 11 //等待一会,然后尝试去中断线程2 12 long start = System.currentTimeMillis(); 13 while(true) { 14 if (System.currentTimeMillis() 15 - start > 5000) { 16 System.out.println("不等了,尝试中断"); 17 thread2.interrupt(); //此处中断读操作 18 break; 19 } 20 } 21 } 22 //两个内部线程 23 class MyThread1 extends Thread{ 24 //线程1处理一些事情,并加上锁 25 public void run() { 26 try{ 27 lock.lock(); 28 System.out.println("开始执行"); 29 //用循环制造一点延时,代表执行的过程没完没了 30 while(true){ 31 int i = 0; 32 if(i>Integer.MAX_VALUE){ 33 break; 34 } 35 } 36 System.out.println("执行完毕"); 37 }finally{ 38 lock.unlock(); 39 } 40 } 41 } 42 43 class MyThread2 extends Thread{ 44 //线程2也处理一些事情,并加上不可中断锁 45 @Override 46 public void run() { 47 try{ 48 lock.lockInterruptibly(); 49 System.out.println(Thread.currentThread().getName()); 50 } 51 catch (InterruptedException e) { 52 System.out.println("不等了"); 53 } 54 finally{ 55 lock.unlock(); 56 } 57 System.out.println("中断成功,去执行其他任务"); 58 } 59 } 60 }
经过仔细的观察,还是让我看到了那个错误的原因,真是苍天不负苦心人啊。错误原因是什么呢?下面就来说说,在我们写 lock.lockInterruptibly()的时候,是需要主动
释放锁的,并且以防万一,要将 lock.unlock()写在 finally中,线程执行的部分(文中就是System.out.println(Thread.currentThread().getName()))要写在 try中,
马虎一看上面的也是按照这么来的,但是问题就在这个最后的finally{ lock.unlock();}上了,按照上面的写法,不管怎样最后都是要执行finally的,也就是要释放锁,但此时
这个线程就是因为苦苦等待锁才要中断的,而你一释放锁是不是就满足了上面的那句话 “当前的线程不是此对象监视器的所有者”,不是你的你还瞎搞,能不报错才怪,于是赶紧的
改过来。
1 class MyThread2 extends Thread{ 2 //线程2也处理一些事情,并加上不可中断锁 3 @Override 4 public void run() { 5 try{ 6 lock.lockInterruptibly();
//在这里用try...finally就不会释放锁了 7 try{ 8 System.out.println(Thread.currentThread().getName()); 9 }finally{ 10 lock.unlock(); 11 } 12 } 13 catch (InterruptedException e) { 14 System.out.println("不等了"); 15 } 16 17 System.out.println("终端成功,去执行其他任务"); 18 } 19 }
既然都写到这里了是不是该把wait()与notify()中的错误也看一看,不过要先吃饭了。。
再看如下的代码,看看错误的原因还是一样,我拿着自己的 锁想打开别人的房子,这是怎么可能的,比人是不是要报警抓你啦!,因此我们只需要将synchronized(thread1)
中的thread1改为test就可以了。
1 public class NotifyTest { 2 3 static NotifyTest test = new NotifyTest(); 4 public static void main(String[] args) throws Exception { 5 6 Thread thread1 = test.new Mythread1(); 7 thread1.start(); 8 Thread.currentThread().sleep(1000); 9 synchronized(thread1){ 10 System.out.println("开始叫醒"); 11 test.notify(); 12 System.out.println("叫醒结束"); 13 } 14 } 15 16 class Mythread1 extends Thread{ 17 public void run() { 18 synchronized(test){ 19 System.out.println(Thread.currentThread().getName()); 20 try { 21 System.out.println("开始等待"); 22 test.wait(Integer.MAX_VALUE); 23 System.out.println("结束等待"); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 } 28 } 29 } 30 }
好啦,这个异常相信以后再遇到就知道怎么修改了...NO,NO 不是的,应该是以后再也不遇到了...不过我倒是有点喜欢碰到异常了,人非圣贤,孰能无错,碰到错误再解决错误
才是让人最高兴的。
---------------------------------------------------------------------------------------------------------------------------------------------------------