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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 史卜坤 中级黑马   /  2012-6-16 10:21  /  1536 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

public class TT extends Thread {
int b = 100;
public synchronized void m1()throws Exception{
b=1000;
Thread.sleep(3000);
System.out.println("m1:"+"b="+b);
}
public  void m2(){
System.out.println("m2"+b);
}
public void run(){
try {
m1();
} catch (Exception e) {
}
}
public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t = new Thread(tt);
t.start();
Thread.sleep(100);
tt.m2();
}
}
答案是 先输出m2的1000 在输出m1的1000,这里我就不懂了,int b = 100,为什么被改变了?我以为m2应该输出还是100的呢?

7 个回复

倒序浏览
我们来看你的函数执行循序
Test tt = new Test();
Thread t = new Thread(tt);  //创建一个新的进程
t.start();  //这个就是run方法开始以一个新进程开始运行,这个时候main方法也在同时运行,是两个线程
Thread.sleep(100);//你让main方法休息了100毫秒,这个时候CPU如果本来在执行main方法的,因为没事干,就回去执行run方法,如果CUP这时候本来只执行run方法,mian方法休息也不影响他,也就是说这个时候不考虑其他程序的影响cpu是去执行run放了,那么就会把b改为1000,然后run方法开始休息3000毫秒,mian方法休息完后开始执行,这个时候b已经是1000了

如果你把mian方法里面休息100毫秒去掉,或者你在m1方法里面重新定义int b = 1000,那么m2就输出100了,因为从始至终,你的整个程序中就只有一个b变量,无论它再何时发生了改变,在这之后对他的引用都是改变后的值!

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
t.start();  
该句会调用run()方法,进而调用m1()方法,将b赋值为1000,此时成员变量b的值变为1000
回复 使用道具 举报
本帖最后由 淡然 于 2012-6-16 11:14 编辑

public class TT extends Thread {
int b = 100;
public synchronized void m1()throws Exception{
b=1000;
Thread.sleep(3000);//b=1000后线程睡眠3秒
System.out.println("m1:"+"b="+b);
}
public  void m2(){
System.out.println("m2"+b);
}
public void run(){
try {
m1();
} catch (Exception e) {
}
}
public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t = new Thread(tt);//这句多余了,tt已经继承了Thread
t.start();
Thread.sleep(100);//主线程睡眠了0.1秒
tt.m2();
}
}

整个过程就是tt线程启动,run方法执行,m1被调用,b=1000,线程睡眠3秒,CPU切换到主线程,
主线程睡眠0.1秒,tt.m2()执行,m2被调用,输出b=1000,3秒后tt继续执行输出m1:b=1000.

“int b = 100,为什么被改变了?我以为m2应该输出还是100的呢? ”
你的b是全局变量,m1调用时执行了b=1000,要想b不被其它函数影响,可以把b定义成m2中的局部变量。
回复 使用道具 举报
  1. package hcy.test.main;

  2. public class Test extends Thread {
  3. int b = 100;
  4. public synchronized void m1()throws Exception{

  5.         Thread.sleep(3000);
  6.         b=1000;
  7.         System.out.println("m1:"+"b="+b);
  8. }
  9. public  void m2(){
  10.         System.out.println("m2:"+b);
  11. }
  12. public void run(){
  13.         try {
  14.                 m1();
  15.         } catch (Exception e) {
  16.         }
  17. }
  18. public static void main(String[] args) throws Exception {
  19.         Test tt = new Test();
  20.         //Thread t = new Thread(tt);
  21.         tt.start();
  22.         //Thread.sleep(100);
  23.         tt.m2();
  24. }
  25. }

  26. 输出结果:
  27. m2:100
  28. m1:b=1000
复制代码

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
本帖最后由 吴小东 于 2012-6-16 11:38 编辑

哥们些抢楼太强力了,等我写完已经到这里了啊!!{:soso_e141:}

首先你new了一个TT对象,然后开启线程
Thread t = new Thread(tt);
t.start();----->>这里就开始调用TT中的run 方法 开始调用m1();
当执行到b=1000;之后又遇到了Thread.sleep(3000);那么t 这个线程就停下来了,此时b的值是1000
接着主线程又遇到Thread.sleep(100); 那么主线程又停下来了
这个时候两个线程都在此停住了,因为主线程的时间是100毫秒 小于m1()中的时间, 所以主线程先醒了然后调用tt.m2();
所以先打印
System.out.println("m2"+b);  m2 1000
然后程序等 t 线程的时间然后执行m1中的方法
System.out.println("m1:"+"b="+b);  m1 b = 1000

Thread t = new Thread(tt);
t.start();
Thread.sleep(4000);--->如果把这里的时间改成大于3000那么 打印结果就是先打印 m1 b =1000 然后是 m2 1000
tt.m2();

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 只要回答得好,不怕没分~~

查看全部评分

回复 使用道具 举报
TT tt = new TT();
Thread t = new Thread(tt);
t.start();线程启动,运行run函数。然后接着又运行m1()方法;然后休息3秒
同时主函数休息100毫秒,时间到运行tt.m2();此时b没改还是100,打印出m2:100
3秒后,启动的线程让使全局变量b=1000,输出m1:b=1000,而新启动的线程是没有运行m2方法的








回复 使用道具 举报
为什么没人发现,他这里的TT本就继承了Thread,为什么还要用new Thread(tt)来启动线程,直接用tt.start那不就可以了~浪费内存~~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马