黑马程序员技术交流社区

标题: 停止线程中碰到的一个小问题,求指教 [打印本页]

作者: 何仕映    时间: 2013-3-23 17:38
标题: 停止线程中碰到的一个小问题,求指教
本帖最后由 何仕映 于 2013-3-24 10:40 编辑

在看到毕老师第十二天停止线程后自己敲代码时,忘记给run()方法上锁了,但是为什么不上锁,线程就不进入冻结状态呢?
请各位大哥大姐给我分析一下,代码的执行过程。
  1. class StopThread implements Runnable
  2. {
  3.         private boolean flag =true;
  4.         public synchronized void run()//为什么这里不加锁为什么线程就不能进入冻结状态呢?
  5.         {
  6.                 while(flag)
  7.                 {
  8.                         try
  9.                         {
  10.                                 wait();
  11.                         }
  12.                         catch (InterruptedException e)
  13.                         {
  14.                                 System.out.println("中断异常");
  15.                         }        
  16.                         System.out.println(Thread.currentThread().getName()+"....run");
  17.                 }
  18.         }
  19.         public void changeFlag()
  20.         {
  21.                 flag = false;
  22.         }
  23. }

  24. class  StopThreadDemo
  25. {
  26.         public static void main(String[] args)
  27.         {
  28.                 StopThread st = new StopThread();
  29.                
  30.                 Thread t1 = new Thread(st);
  31.                 Thread t2 = new Thread(st);

  32.                 t1.start();
  33.                 t2.start();

  34.                 int num = 0;

  35.                 while(true)
  36.                 {
  37.                         if(num++ == 60)
  38.                         {
  39.                                 st.changeFlag();
  40.                                 break;
  41.                         }
  42.                         System.out.println(Thread.currentThread().getName()+"......."+num);
  43.                 }
  44.                 System.out.println("over");
  45.         }
  46. }
复制代码

作者: blackcaismine    时间: 2013-3-23 17:59
本帖最后由 blackcaismine 于 2013-3-23 18:00 编辑

额,我试了一下你的代码,是可以终止的,但是运行过程中会产生一个问题就是有IllegalMonitorStateException异常。
IllegalMonitorStateException是当前的线程不是此对象监视器的所有者时抛出的异常,也就是说在线程1仍旧指向run方法内使用wait()的时候,线程2
试图插入进来使用wait()产生了错误。所以加上了锁就可以防止这样的情况发生。
但是不加锁即便会产生问题,这段代码仍旧能够停止。。
作者: 何仕映    时间: 2013-3-23 18:45
blackcaismine 发表于 2013-3-23 17:59
额,我试了一下你的代码,是可以终止的,但是运行过程中会产生一个问题就是有IllegalMonitorStateException ...

我知道仍能停止,我问的是为什么不加锁,就是上面代码注释的那一行,为什么不加synchronized,线程就不进入冻结状态,加上同步以后就进入冻结状态。按理说加不加锁,都会进入冻结状态的啊。麻烦你指点一下,谢谢。
作者: blackcaismine    时间: 2013-3-23 19:04
本帖最后由 blackcaismine 于 2013-3-23 19:05 编辑
何仕映 发表于 2013-3-23 18:45
我知道仍能停止,我问的是为什么不加锁,就是上面代码注释的那一行,为什么不加synchronized,线程就不进 ...

按我的理解是,不加同步,一个线程使用wait()后,另一个线程再用wait()根本不起作用,直接报异常,所以无法冻结。
作者: 何仕映    时间: 2013-3-23 19:07
blackcaismine 发表于 2013-3-23 19:04
按我的理解是,不加同步,一个线程使用wait()后,另一个线程再用wait()根本不起作用,直接报异常,所以无 ...

就算只有一个起作用,那也应该程序结束也不会结束啊。可程序还是结束了啊?
作者: blackcaismine    时间: 2013-3-23 19:32
本帖最后由 blackcaismine 于 2013-3-23 19:34 编辑
何仕映 发表于 2013-3-23 19:07
就算只有一个起作用,那也应该程序结束也不会结束啊。可程序还是结束了啊? ...

抱歉,刚刚我也不太清楚为什么会这样。
于是我将t2线程注释掉,然后未加同步进行执行,
结果发现,即便只有一个线程访问未加锁的wait() 也会出现异常,因此无效。
你可以试验下,如果这样的话那么就可以解释为何两个线程都不会冻结了。
作者: filter    时间: 2013-3-23 19:43
                while(true)

                {

                        if(num++ == 60)

                        {

                                st.changeFlag();

                                break;

                        }

                        System.out.println(Thread.currentThread().getName()+"......."+num);

                }
还是这段代码出的问题,当线程t1或t2,开始执行,调用run方法,进入等待,
由于没有加锁,这个时候主线程可能会抢到执行权,开始执行主线程while循环部分,
所以抛出IllegalMonitorStateException,主线程和自定义线程的锁不一样
run方法加了同步之后,t1,t2两个线程执行不会受干扰
作者: blackcaismine    时间: 2013-3-23 19:54
李志阳 发表于 2013-3-23 19:43
while(true)

                {

不是吧,主线程执行while循环怎么会抛出IllegalMonitorStateException??
wait()方法并没有被主线程访问到。
作者: filter    时间: 2013-3-23 20:33
blackcaismine 发表于 2013-3-23 19:54
不是吧,主线程执行while循环怎么会抛出IllegalMonitorStateException??
wait()方法并没有被主线程访问 ...

嗯,刚吃饭回来,刚刚也觉得不太对劲,不好意思
还是wait方法出的问题,没有制定锁就会抛出IllegalMonitorStateException




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2