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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张源锋 中级黑马   /  2013-4-1 23:11  /  1467 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 无奈№追夜 于 2013-4-2 17:34 编辑
  1. package Test1;

  2. public class Test extends Thread {
  3.                 int b = 100;
  4.                
  5.                 public synchronized void m1() throws Exception{
  6.                         //Thread.sleep(2000);
  7.                         b = 1000;
  8.                         Thread.sleep(5000);
  9.                         System.out.println("b = " + b);
  10.                 }
  11.                
  12.                 public synchronized void m2() throws Exception {
  13.                         Thread.sleep(2500);
  14.                         b = 2000;
  15.                 }
  16.                
  17.                 public void run() {
  18.                         try {
  19.                                 m1();
  20.                         } catch(Exception e) {
  21.                                 e.printStackTrace();
  22.                         }
  23.                 }
  24.                
  25.                 public static void main(String[] args) throws Exception {
  26.                         Test tt = new Test();
  27.                         Thread t = new Thread(tt);
  28.                         t.start();
  29.                         
  30.                         tt.m2();
  31.                         System.out.println(tt.b);
  32.                 }
  33.         }
复制代码
结果:
1000
b = 1000
m1()方法最打印的为什么不是200???main方法打印的为什么不是200???求解
还用
  1.                 public  void m2() throws Exception {
  2.                         Thread.sleep(2500);
  3.                         b = 2000;
  4.                 }
  5.                
复制代码
若改成如上这是结果是都是2000,为什么啊,头大

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

4 个回复

倒序浏览
问题解决了吗,哥们?我的解释如下,表达有点混乱,哪里没看懂继续留言
  1. class Test extends Thread {
  2.                 int b = 100;
  3.                
  4.                 public synchronized void m1() throws Exception{
  5.                         //Thread.sleep(2000);
  6.                         b = 1000;
  7.                         Thread.sleep(5000);
  8.                         System.out.println("b = " + b);
  9.                 }
  10.                
  11.                 public synchronized void m2() throws Exception {//有锁,运行时只能运行一个线程
  12.                         Thread.sleep(2500);
  13.                         b = 2000;
  14.                 }
  15.                
  16.                 public void run() {
  17.                         try {
  18.                                 m1();//这个地方只执行m1
  19.                         } catch(Exception e) {
  20.                                 e.printStackTrace();
  21.                         }
  22.                 }
  23.                
  24.                 public static void main(String[] args) throws Exception {
  25.                         Test tt = new Test();
  26.                         Thread t = new Thread(tt);
  27.                         t.start();//开启t的线程,同时执行run函数,这时候只执行m1,m1会沉睡5秒,所以会先向下执行                        
  28.                         tt.m2();//这里,虽然执行m2,但是沉睡了2.5秒,所以main线程继续向下执行。
  29.                         System.out.println(tt.b);//这时候,首先输出b,因为在m1沉睡钱被赋值,所以此时一定为1000,main线程结束,这个时候先等待唤醒t线程,不会因为m2沉睡2.5秒,m2先醒来。因为t唤醒后执行b的输出语句,就是10000
  30.                 }
  31.         }
  32.                 /*
  33.                                 public  void m2() throws Exception
  34.                         Thread.sleep(2500);
  35.                         b = 2000;
  36.                 如果用上面的语句替换m2,那么m2和m1没有同步,这样的话,m2沉睡2.5秒就会醒来,m1和这个线程没有同步,m1沉睡5秒,这个时候b会被赋值,最终值b为2000,所以输出的b都是2000
  37.                
  38.                 */
复制代码

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
开启t线程,执行代码,run方法,m1中,b被赋值为1000,然后沉睡5000毫秒,不继续执行,往下走。到m2,直接sleep2500毫秒,不执行b=2000,继续往下走。此时到达main函数的输出语句,所以main函数输出了b值为1000.等待进程被唤醒,此时m1和m2是同步的,所以只好等待t线程被唤醒,执行m1,输出了b=1000.然后m2才会执行,b被赋值为2000.
代码修改去掉同步后,b会在m2中被赋值,然后在继续执行,就是这有区别,所以打印结果不同。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
我的理解:本例一共就2个线程:线程t和主线程。线程t.start后,究竟是t先运行还是主线程先运行,取决于cpu。因此可能有不同结果。
运行多遍,主线程先运行完这种情况也不奇怪。想要看到t先运行,可以在main方法中加一个sleep语句,让主线程冻结。
  1.                 public static void main(String[] args) throws Exception {
  2.                         Test tt = new Test();
  3.                         Thread t = new Thread(tt);
  4.                         t.start();
  5.                         try
  6.                         {
  7.                                                         Thread.sleep(10);
  8.                         }
  9.                         catch (Exception e)
  10.                         {
  11.                         }
  12.                         tt.m2();
  13.                         System.out.println(tt.b);
  14.                 }
复制代码
这时,结果与之前就会不同。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
首先就是本例main中一共两个线程,一个主线程一个子线程。子线程start()运行tt.run(){m1()}沉睡5秒。
此时主线程同时可以执行tt.m2();因为m1(),m2()互斥,所以m2()不能执行,主线程继续向下执行到System.out.println(tt.b);
tt.b已经被m1()修改成了1000所以先打印 1000
然后tt.m1()沉睡结束打印 b = 1000,
然后执行m2()中的吧= 2000;
如果main()最后加上Thread.sleep(5000+2500);System.out.println(tt.b);在打印就会使m2中给定的2000了。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马