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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Neverbelazy 中级黑马   /  2013-5-14 23:15  /  2322 人查看  /  18 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 Neverbelazy 于 2013-5-15 00:39 编辑

有如下一段代码:
需求:newThread运行 判断 which(!flag) i++; 主函数设定过1秒钟,更改flag
结果, 按原始程序 newThread中 无限循环;a处代码不被运行到   System.out.println(i) 没有被打印
但是,如果b处按注释修改,则不会无限循环

------------------------------------------------------------------------------------------------
程序中看不出有什么问题,但是却有如此奇怪的结果, 请高手解答!
  1. public class ConcurrencyTest {
  2.           private static boolean flag;
  3.           public static void main(String[] args) throws InterruptedException {

  4.           Thread newThread=new Thread(new Runnable(){ //newThread线程构造
  5.            public void run(){
  6.                       int i=0;
  7.                       while(!flag)
  8.                             {  i++; }   // --> b. 可是,如果此句换成{ System.out.println(i++);} // 就可以打印出结果,程序循环打印一段后停止
  9.                       System.out.println(i); // --> a.  打印看i在多少的时候 flag被改变了
  10.                     }
  11.             });

  12.           newThread.start();
  13.           TimeUnit.SECONDS.sleep(1); // 挂起1秒
  14.           flag=true; // 改变flag企图让newThread的while循环停止
  15.           }
  16. }
复制代码
--------------- 由于2# xuemeng同学的误解,程序上加上了{ }, 以避免造成歧义 -------------
-------------------------------------- 不确定的答案 -------------------------------------------------------------
--------------- xuemeng同学的截图结果是正确的,那就暂时认为是JVM不同导致的吧---------------

评分

参与人数 1技术分 +1 收起 理由
袁梦希 + 1

查看全部评分

18 个回复

倒序浏览
本帖最后由 xuemeng 于 2013-5-14 23:50 编辑

粗心害死人, 哈哈!!1

01.public class ConcurrencyTest {

02.          private static boolean flag;

03.          public static void main(String[] args) throws InterruptedException {

04.

05.          Thread newThread=new Thread(new Runnable(){ //newThread线程构造

06.           public void run(){

07.                      int i=0;

08.                      while(!flag)//你的while循环没有大括号啊, 那么当程序执行while循环的时候,就只会执行i++, 执行i++ 然后判断while循环的条件, 然后再执行i++, 再循环判断,一直死循环, 当一秒中的时间到了之后, 那么就打印出一个i的值,      如果这里换成输出语句, 那么当然能够一直打印啊, 因为 你一进入while循环, 那么就执行输出语句, 然后再循环, 再执行输出语句, 知道你停止的时间到,然后改变循环条件.   你的代码如果非要   i ++;  System.out.pirntln(i)这样写, 那么while就要加大括号, 把  i++ 和 System.out.println(i)这两句代码都括起来, 这样while循环才会执行这两句代码,而不是仅仅执行i++一句代码. 具体修改代码我再写一下;
                           

09.                              i++;    // --> b. 可是,如果此句换成 System.out.println(i++); // 就可以打印出结果,程序在一段循环后停止

10.                      System.out.println(i); // --> a.  打印看i在多少的时候 flag被改变了

11.                    }

12.            });

13.

14.          newThread.start();

15.          TimeUnit.SECONDS.sleep(1); // 挂起1秒

16.          flag=true; // 改变flag企图让newThread的while循环停止

17.          }

18.}


修改代码如下::

public class Demo {
private static boolean flag;
public static void main(String[] args) throws InterruptedException {
  Thread newThread = new Thread(new Runnable() {
   public void run() {
    int i = 0;
    // 就是在while循环加了个大括号就行了
    while (!flag) {
     i++;
     // 加上括号后, 这段输出语句也在while循环里面了
     System.out.println(i);
    }
   }
  });
  newThread.start();
  TimeUnit.SECONDS.sleep(1);
  flag = true;
}
}




回复 使用道具 举报
xuemeng 发表于 2013-5-14 23:41
粗心害死人, 哈哈!!1

01.public class ConcurrencyTest {


我就只想执行 i++;

while(!flag){i++;} //这样写也行

在主程序中,改变flag=true了 循环理应停止 然后 执行 System.out.println(i);

但是结果却 不是这样。。。
回复 使用道具 举报
你这个代码当然是先执行线程啊, 然后再改变条件啊
回复 使用道具 举报
Neverbelazy 发表于 2013-5-14 23:45
我就只想执行 i++;

while(!flag){i++;} //这样写也行

你不是问为什么你那样写 不会打印很多数字再停止的原因吗???

点评

不是,我不是纠结在 打印上 而是纠结在程序是否能够 ……停止循环  发表于 2013-5-14 23:59
回复 使用道具 举报
本帖最后由 xuemeng 于 2013-5-14 23:58 编辑

  你先看好,我的大括号是加在哪个位置的!!
运行一下我修改的代码   我的大括号是把
while (!flag) {
     i++;
System.out.pirntln(i)
}  这两句括起来了, 而不单单是i++  ;'

如果代码像你那样加,如下:
while(!flag) {
     i ++;
}
System.out.println(i);   , 这样while循环加了大括号和没加是一样的!!!1
回复 使用道具 举报
xuemeng 发表于 2013-5-14 23:41
粗心害死人, 哈哈!!1

01.public class ConcurrencyTest {

是这样, 不要看我b的情况了,就是单独a的情况
while(!flag)
{i++;}
System.out.println(i); 在我的电脑上不能被打印这句,程序一直循环。

注: 我提出的b的情况只是让这个问题更奇怪, 因为换成b,竟然程序就在连续打印了0- n 后正常的停止了
回复 使用道具 举报
本帖最后由 xuemeng 于 2013-5-15 00:05 编辑
Neverbelazy 发表于 2013-5-14 23:56
是这样, 不要看我b的情况了,就是单独a的情况
while(!flag)
你这样写,你的代码怎么可能执行的到System.out.println(i)这句代码?  你的i一直在那里自增, 等到循环条件改变, 然后跳出循环, 接着才执行下面的输出语句, 于是就打印了一个值
{i++;}

  你运行一下我写的代码就清楚了,   你的while循环有个范围啊!!
   你只是把i++括起来, 那么它就只会执行i++啊
回复 使用道具 举报
xuemeng 发表于 2013-5-14 23:56
你先看好,我的大括号是加在哪个位置的!!
运行一下我修改的代码   我的大括号是把
while (!flag) {

确实是一样的 就是因为你理解错了我的意思我才又加上的,,,比如就是 a 这种情况,我想知道你的电脑上是否能够打印出来 最后的这个 i;  
回复 使用道具 举报
Neverbelazy 发表于 2013-5-14 23:45
我就只想执行 i++;

while(!flag){i++;} //这样写也行

结果是那样啊, 我运行都没问题啊,  不过你这样写只会打印一个值出来,就是在条件改变之后, 然后循环停止,就打印一个值!!

点评

好吧 那只可能是我电脑的问题了。。。。  发表于 2013-5-15 00:12
回复 使用道具 举报
xuemeng 发表于 2013-5-15 00:03
你运行一下我写的代码就清楚了,   你的while循环有个范围啊!!
   你只是把i++括起来, 那么它就只会执行i ...

额。。。。我清楚你的意思,我不想 把所有的 i 都打印

我只是奇怪为什么
while(!flag)
{i++;}
这句话会无限循环

但是
while(!flag)
{System.out.println(i++);}
就不会无限循环
回复 使用道具 举报
Neverbelazy 发表于 2013-5-15 00:06
确实是一样的 就是因为你理解错了我的意思我才又加上的,,,比如就是 a 这种情况,我想知道你的电脑上是 ...

当然能打印出来,就你的代码, 能打印出来!!不过你的代码只能打印一个i , 你要等程序运行一下, 就能看到结果了, 因为你的程序一直处于等待状态, 在等待状态的时候, i 的值一直在做自增运算, 等到循环条件改变, 循环结束,接着执行输出语句, 就打印出来一个值啊

点评

ok 我只能归结到是我电脑的问题了,在我的电脑上面,过了2分钟都没有打印 最后的 i ;  发表于 2013-5-15 00:15
回复 使用道具 举报
Neverbelazy 发表于 2013-5-15 00:10
额。。。。我清楚你的意思,我不想 把所有的 i 都打印

我只是奇怪为什么

while(!flag) {
    System.out.println(i++);
}
这个代码也会无线循环啊, 你再运行一下看看?  怎么可能不是无限循环呢?
   这个代码一样的, 只有等到循环条件为false, 循环才会停止!!
  
回复 使用道具 举报
xuemeng 发表于 2013-5-15 00:12
当然能打印出来,就你的代码, 能打印出来!!不过你的代码只能打印一个i , 你要等程序运行一下, 就能看到结 ...

怎么可能, 不会是字节码文件弄错了吧E!1  你有没有导包??
   然后之前又写过类似的代码?  以至于最终导致出错!!
  不然就你发上来的代码一点问题都没有的
回复 使用道具 举报
本帖最后由 、__WSD吴少东 于 2013-5-15 00:24 编辑

我不确定是不是这个原因,只是猜测,因为没办法证实,我只是根据在里面放入打印语句后结果不是相同的,再加上老毕说的等待唤醒机制,猜测到的,

当主线程等待一秒钟后,获得执行权,但是,不一定执行,再加上,while循环里面只有一个 i++;  主线程抢到执行的概率非常低,低到基本抢不到,

猜测,猜测啊...如果一直挂着,主线程应该会抢到执行的,我的渣渣电脑不行,所以我就没做这个上面的测试,

以上只是我的个人猜测,具体是不是我就不大清楚了...感觉应该就是这个原因,上边的测试就没问题,应该是电脑性能的缘故...

点评

额,对于a 我已经试过N次,等过N久;但是还是不行,但是b的情况基本上5秒停止  发表于 2013-5-15 00:30
回复 使用道具 举报
xuemeng 发表于 2013-5-15 00:15
while(!flag) {
    System.out.println(i++);
}

额,,,我已经认为是我电脑的问题了 好吧 我再解释一下

1. 我清楚 我希望的打印结果是     a. 当flag=true, 只打印最后一次 i;  b. 打印很多次,直到flag=true;
2. 但是,在我的电脑的实际情况   a. 无限循环,N久都不打印结果    b. 打印很多此,直到 flag=true;

所以,我才有了我的问题。

如果你的电脑上面,如你所说,是1.中期望的打印结果一样,可能就是我电脑JVM的问题了

我想等等看,是否还有别人也是和你得到一样的正常的结果

如果是,那就更确信了是我电脑JVM的问题
回复 使用道具 举报
Neverbelazy 发表于 2013-5-15 00:26
额,,,我已经认为是我电脑的问题了 好吧 我再解释一下

1. 我清楚 我希望的打印结果是     a. 当flag=tr ...

哦!!
    那就搞不懂了额!
回复 使用道具 举报
本帖最后由 xuemeng 于 2013-5-15 00:33 编辑

我的截图:  我截图的代码和你的源代码一模一样!  至于加在i++那里的大括号,那样加, 可有可无

未命名.jpg (199.79 KB, 下载次数: 0)

未命名.jpg
回复 使用道具 举报
xuemeng 发表于 2013-5-15 00:32
我的截图:  我截图的代码和你的源代码一模一样!  至于加在i++那里的大括号,那样加, 可有可无 ...

额 可能是JVM不一样吧 我决定放弃这个问题了。  :dizzy:
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马