A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 罗广伟 中级黑马   /  2013-6-15 09:41  /  2196 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  1. class Test
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Run r=new Run();
  6.                 Thread t1=new Thread(r);
  7.                 Thread t2=new Thread(r);
  8.                 //t2.setDaemon(true);
  9.                 //t1.setDaemon(true);
  10.                 t1.start();
  11.                 t2.start();
  12. t2.setDaemon(true);
  13. t1.setDaemon(true);
  14.                
  15.                 for(int x=0;x<10;x++)
  16.                 {
  17.                         System.out.println("=");
  18.                 }
  19.                 r.set();
  20.                 System.out.println("over");
  21.         }
  22. }
  23. class Run implements Runnable
  24. {
  25.         private boolean flag=true;
  26.         public synchronized void run()
  27.         {
  28.                 while(flag)
  29.                 System.out.println(Thread.currentThread().getName()+"==gogo");
  30.         }
  31.         public void set()
  32.         {
  33.                 flag=false;
  34.         }
  35.        
  36. }
复制代码
问题位置:多线程12天08,视频中毕老师说setDaemon()需要在线程开启之前设置,这样非守护线程结束,守护线程自行结束。可是当setDadmon()写在线程开启之后只运行t1.t2程序不停止,这是为什么?

评分

参与人数 1技术分 +1 收起 理由
Super_Class + 1 神马都是浮云

查看全部评分

6 个回复

倒序浏览
有没有发现运行时有异常啊,运行太快可能没看到,在运行结果最开始的时候。加个sleep就看到了
Exception in thread "main" java.lang.IllegalThreadStateException
        at java.lang.Thread.setDaemon(Thread.java:1365)
        at Text.main(Text.java:10)

然后setDaemon()方法上写有,该方法必须在启动线程前调用。否则
抛出:
IllegalThreadStateException - 如果该线程处于活动状态。就好像给这个线程加属性,应该在没运行的时候加,运行了就没法改变了

评分

参与人数 1技术分 +1 收起 理由
孙百鑫 + 1

查看全部评分

回复 使用道具 举报
异常是穿插着打印出来,我也想知道为什么
D:\javafile\day13>java Tiezi
Exception in thread "main" Thread-0==gogo
Thread-0==gogo
Thread-0==gogo
Thread-0==gogo
Thread-0==gogo
Thread-0==gogo
java.lang.IllegalThreadStateExceptionThread-0==gogo

Thread-0==gogo
        at java.lang.Thread.setDaemon(Thread.java:1365)Thread-0==gogo

        at Tiezi.main(Tiezi.java:16)
Thread-0==gogo

下面疯狂打印Thread-0==gogo

评分

参与人数 1技术分 +1 收起 理由
孙百鑫 + 1

查看全部评分

回复 使用道具 举报
这个问题和守护线程的设置没关系,问题在于线程的run()方法中while循环是死循环,而且还没有睡眠,那么Thread-0线程就一直占用run()方法,所以一直是:Thread-0==gogo
这样循环下去。所以应该在while()循环中加入 try{  Thread.sleep(100);}catch(Exception e){},这样其他线程才有机会去调用run()方法。

评分

参与人数 1技术分 +1 收起 理由
孙百鑫 + 1

查看全部评分

回复 使用道具 举报
主函数运行后,两个线程开启,这时候无法再设置守护线程。运行结果开头处抛出异常。说明设置失败,并且这两句代码不运行,由于抛出的是Exception,所以不影响主函数运行。
Exception in thread "main" java.lang.IllegalThreadStateException
        at java.lang.Thread.setDaemon(Thread.java:1365)
        at Test.main(1111.java:12)

我改了下两个线程的开启顺序,发现开启t2线程后,运行结果为这个线程无限循环。说明线程开启后,直接运行了一次,线程主体是一个死循环,并且封在同步函数内,所以该线程不执行完,其他线程无法执行。所以先抛出后台线程的设置异常,然后进入单一线程的同步死循环。

个人理解。希望有所帮助。

评分

参与人数 1技术分 +1 收起 理由
孙百鑫 + 1

查看全部评分

回复 使用道具 举报
不好意思,刚刚顺手写错了一个地方,就是到在主函数内抛出了异常后,主线程就停止运行,所以后面调用set方法来停止循环的语句就执行不到了。造成了线程的循环。
补充一下,你的这个同步函数内并没有操作共有数据,只是单纯的打印操作。所以我刚刚删除了synchronized关键字,运行一次,除了开始时抛出了后台线程设置的异常外,线程的运行状况正常。说明程序进入死循环,就是因为抛出异常后,主线程不继续运行,执行不到后续的限制条件。

希望能有所帮助
回复 使用道具 举报
楼主您好~帖子长时间未作出回答,我已经将您的帖子改成已解决。如果有问题的话可以私密我哦~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马