import java.util.*;
public class TT implements Runnable{
public int i =100;
public synchronized void m1(){
i=1000;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i="+i);
}
public void m2(){
i=2000;
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
m1();
}
public static void main(String [] args){
TT tt = new TT();
Thread tr=new Thread(tt);
tr.start();
tt.m2();

}
}
说出输出什么,为什么。

解决方案 »

  1.   

     //我用的是jdk 1.5以上
      

  2.   

    1000 2000 2000 1000 2000 2000 1000我觉的是这样子的  呵呵  main 执行后  线程启动 默认执行run() 方法   执行m1 输出100  睡眠 5000 毫秒
    然后执行 m2 输出  2000 然后睡眠2500  当m2 输出玩再执行时 由于 m1 还在睡眠中 M2 又执行了一边
      

  3.   

    public static void main(String [] args){
        TT tt = new TT();
        tt.m2();
    }你试着把main改成这样,看看结果就知道了
      

  4.   

    答案:i=1000
    先运行Main 主线程 TT tt = new TT();Thread tr=new Thread(tt);定义一个Thread类
    然后调用tr.staart()实际上是执行了run(),在run()里面有m1()方法,产生结果i=1000
    至于tt.m2();没有结果输出
            
      

  5.   

    应该是输出i=1000
    因为在调用m2方法的时候,资源i还在被线程tr控制着,后边的i=2000的赋值语句不会起作用。
    个人观点仅供参考
      

  6.   

    答案i = 1000
    public synchronized void m1(){
    m1被同步当线程在调用m1时i无法被m2访问
    在m1里面 i被赋值1000再打印所以一直输出1000
      

  7.   

    有没有SYCHRONIZED 结果都是一样的,都只输出1000
      

  8.   

    估计没有输出结果,m1被同步了,没释放,tr用不了m1,谁运行一下看看,我的JCreator用不了了,要注册
      

  9.   

    这个运行的顺序应该是主线程 在tr线程开启后 m2和m1争夺优先权 如果m2先运行 就会把i先赋值成2000然后sleep状态,在这时m1开始运行了,他会把i再赋值成1000然后再Sleep 再输出i=1000 因为m1是同步的 所以只有当m1运行完以后m2才会sleep结束;如果优先权在m1那里就是m1运行完再运行m2
      

  10.   

     俺真鄙视你,说什么m1被同步了,m2不能访问i ??????
       那你把m2中的Thread.sleep(2500),放在i=2000前面,再看看输出??
      情况不是这样的。 我已经知道大概情况了,但还有点疑惑,来点权威的点评。
      

  11.   

    1000、2000都有可能,和sychronized无关。
    但实际运行肯定是1000。
      

  12.   

    import java.util.*;
    public class TT implements Runnable{
        public int i =100;
        public synchronized void m1(){
            i=1000;
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("i="+i);
        }
        public void m2(){
    //此处改了顺序
         try {
                Thread.sleep(2500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            i=2000;
        }
        @Override
        public void run() {
            m1();
        }
        public static void main(String [] args){
            TT tt = new TT();
            Thread tr=new Thread(tt);
            tr.start();
            tt.m2();
            
        }
    }
      

  13.   

    可能是 2000,也可能是 1000,因为你  tr.start();启动了线程,线程进入可运行状态,但是你的main方法并没有结束,main方法也是一个线程,是main线程 如果main线程比tr先抢到时间片,那么m2先执行,那么输出结果就是2000,如果tr先抢到时间片,那么输出1000.线程之间是抢占式的
      

  14.   

    结果应该是1000吧,因为再向控制台输出i的值之前,才把1000赋值给i,所以不管m1和m2中各自sleep多长时间,结果是不变的
      

  15.   

    除了极为特殊的巧合,m1中赋值未输出,m2中赋值,然后m1才输出结果。
      

  16.   

    有意思吖,我粘贴到Eclispse里,public void run()这行竟然报错了。
      

  17.   

    把@Override删除了以后,可以运行了,结果1000.
    被你们搞晕了,每一个线程都有自己独立的内存空间,互不干扰。当你创建一个新线程的时候,本线程中实例变量的变动与其他线程无关。
      

  18.   

    16楼的加了个out,你看看就知道了
    package test;public class TT implements Runnable {
    public int i = 100; public synchronized void m1() {
    System.out.println("m1");
    i = 1000;
    try {
    Thread.sleep(5000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println("i=" + i);
    } public void m2() {
    // 此处改了顺序
    System.out.println("m2");
    try {
    Thread.sleep(2500);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    i = 2000;
    } public void run() {
    m1();
    } public static void main(String[] args) {
    TT tt = new TT();
    Thread tr = new Thread(tt);
    tr.start();
    tt.m2(); }
    }
      

  19.   

    试了好几次,每次打印出来的都是1000,
    比较认同8L的看法,因为在调用tr.start()方法的时候,资源i还在被线程tr控制着,后边的i=2000的赋值语句不会起作用。 
      

  20.   

    这个和次序没有什么关系吧:
    参照运行后的结束,我的理解是这样的:
    Test_Thread tt = new Test_Thread();
    Thread tr=new Thread(tt);
    tr.start();
    tt.m2();这里,Test_Thread tt = new Test_Thread();
    Thread tr=new Thread(tt);
    tr.start();
    因为是多线程运行,所以要考虑哪个建筑第一时间取得cpu,所以要分两种情况:(1)tr.start()先开始:
    先新建了一个线程tr,并启动它,tr.start()调用的是tr的run()方法,也就是新建Test_Thread的run()方法
    调用m1(),将i付值为1000,然后tr线程挂起,m1()用synchronized修饰,数据i在方法m1()中使用,所以i被锁,
    再调用tt.m2(), i=2000;这里访问了受保护资源,付值失败,i仍为1000,然后tt线程挂起,
    2500ms后,tt休眠时间到,i仍为1000,tt线程结束,
    5000ms后,tr休眠时间到,i仍为1000,tr线程结束.(2)tt.m2()先开始:
    将i付值为2000,然后tt挂起,此时i值为2000,
    tr.start()启动,m2()没有对i进行保护(加锁),所以m1()可以修改i的值,将i设置为1000,并保护加锁,然后挂起,
    2500ms后,tt休眠时间到,i被m1()设置为1000,tt线程结束,
    5000ms后,tr休眠时间到,i为1000,tr线程结束.所以楼主的这个程序,应该是输出1000,1000/2000,1000
      

  21.   

    哦,sorry因为测试,改动了楼主的程序,在m2里加了一个打印,呵呵,按楼主的程序,结果都是1000
      

  22.   

    输出结果:i=1000;而且一定是输出:i=1000;
    如果你在 public void m2(){
            i=2000;
            try {
                Thread.sleep(2500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }这段代码的catch语句块中在写一句“System.out.println(i);",那输出结果就会变成:
    1000
    i=1000;
    你这段代码应该是尚学堂马士兵老师JAVA视频上的例题吧,如果不是的话,我建议你到网上下一些马老师的视频看看,它上面就有这样的例子!相信你一定可以懂的!这里我就不罗嗦了!
      

  23.   

    对照了API重新总结了下楼主提出的问题:
    1.首先,synchronized关键字不管加在类声明上还是加在方法声明上,它所作的工作只是锁定对象,而对于其内部的方法和变量不做“私有”锁定.也就是同一对象就算有synchronized但是其中同一变量还是能被对象中不同方法访问.
    2.接下来看楼主提出的问题,从main开始,到tr线程start(),此时开始有tr线程和main线程同步执行,在楼主的程序中,线程执行先被main抢占,执行完i=2000,然后main开始sleep()挂起,tr线程执行i=1000,然后sleep()到结束.tr线程执行最后打印i=1000.至于为什么先执行的是main线程中的i赋值,这是jvm内部机制决定的,在此不做探讨.
    3.下面问题的重点来了,究竟synchronized有没有锁定i.楼主可以用下面这段代码测试下:
        public static void main(String [] args){
            TT tt = new TT();
            Thread tr=new Thread(tt);
            tr.start();
            System.out.println("1");
            tt.m2();
        }
    在tt.m2()执行之前执行一个额外的方法.此时线程的调用过程变为:
    (1)System.out.println("1");被首先执行,main线程时间片使用完毕
    (2)tr线程开始执行i=1000,开始sleep()休眠(注意,此时tr线程并未结束,synchronized仍旧锁定对象).
    (3)main线程执行tt.m2(),i=2000赋值成功,开始休眠(若是i被锁定,m2此时不应该能访问)
    (4)tr休眠结束(应该说是m2()休眠先结束,没影响),执行打印方法.综上,如前所述,解释了楼主提出的问题.而后面提出的测试代码的分析就是楼主第二个问题的答案:
    因为m2()中先进行休眠,tr线程中首先赋值i=1000然后休眠,在tr休眠未结束之前m2()被唤醒执行i=2000,所以tr线程执行到打印方法时i的值已经为2000了.另外,楼上很多人说的synchronized锁定的是对象内部的变量或方法的说法是不正确的.
      

  24.   

    因此楼主16楼的结果就很明显了,m1先赋值,m2后赋值,并且m1是在m2执行后进行打印,所以打印结果是2000
      

  25.   

    前面说过了,1000、2000都有可能,和sychronized无关。但实际运行肯定是1000。
    详细解释一下吧。
    首先,这个问题和synchronized无关。你的synchronized又没有锁变量,这里也不是2个线程调m1,所以synchronized是没影响的。
    这个和sleep时间也没有关系。就是主线程的tt.m2()和tr谁先谁后,输出后执行里的那个赋值。
    你在tr.start();和tt.m2();之间加上Thread.sleep(1);模拟主线程被阻隔的效果,就输出2000了。
      

  26.   

    补充下:楼主第一楼的问题的确与sleep无关,但是16L的问题结果由sleep时间决定,并不是主线程阻隔的问题.楼主的问题我觉得用16L的代码最能体现出这个问题的实质.
      

  27.   


    16楼的代码,和我在tr.start();和tt.m2();之间加上Thread.sleep(1);本质相同,都是让m2方法赋值语句晚一点执行,具体说就是在m1线程sleep的时候执行。
      

  28.   

    应该是2000
    tr.start();  调用了run() ----m1()sleep(5000)
    这时调用了m2() 给i重新赋值为2000
      

  29.   

    关键一点:
    tt.m2();坑定100%比m1()先执行。
    我觉得这可能是因为tt.m2()属于main,而主线程优先级尤其高的关系。所以绝对是输出1000
    16的代码在tt.m2()中将i的赋值语句置于sleep之后了,所以为m1()争取了时间ps:和synchronized 无关