zoukankan      html  css  js  c++  java
  • 都不想有错误,但一不小心就犯了

    -------------------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 不是的,应该是以后再也不遇到了...不过我倒是有点喜欢碰到异常了,人非圣贤,孰能无错,碰到错误再解决错误

    才是让人最高兴的。

    ---------------------------------------------------------------------------------------------------------------------------------------------------------

  • 相关阅读:
    JVM,反射与动态代理
    11款实用的一句话网站设计代码
    Winform TextBox中只能输入数字的几种常用方法(C#)
    列表checkbox全选
    函数调用约定
    vs编译后在本机能运行,在别的机器上运行提示runtime Error的问题
    学习地形编程(一)
    Ogre中动态三维鼠标的实现
    讲讲volatile的作用
    绕任意轴旋转的推导
  • 原文地址:https://www.cnblogs.com/Jc-zhu/p/4435613.html
Copyright © 2011-2022 走看看