版主你秀逗了吧。。从1加到50,不是50+50.。最大值是2550
同学,你再看看题?不是sum=sum+i哦~

解决方案 »

  1.   

    public class Threads implements Runnable {
    public int sum = 0;
    /**
     * @param args
     */
    public static void main(String[] args) {
    Threads ts = new Threads();
    Thread t1 = new Thread(ts);
    Thread t2 = new Thread(ts);
    t1.start();
    t2.start();
    try {
    Thread.sleep(5000);//保证两个线程都执行完
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println(ts.sum);
    } public void run() {
    for (int i = 1; i <= 50; i++) {
    sum=sum+i;
    }
    }}
    sum=2550
      

  2.   

    完全错误,题目说的是sum=sum+1,而且你sum不是共用的.
      

  3.   

    我的答案是2-100.只需要考虑一定在范围之内并且能够都被取到就可以了.
    首先不可能超过100.
    其次不管是哪个线程,当允许最后一次的求和时取到的sum值一定是被加上的,即便是被另外一个线程修改过,也一定是加上过的,所以一定取得的sum值最小是1,那么加上之后结果一定不小于2.
    那么一定是2-100之间的值。现在考虑所有的都可能被取到。
    对于50-100之间比较好理解。让其中一个线程取加sum到0-50之间的值,然后另外一个线程取到这个值,第一个线程运行完成之后,再由第二个线程取到在刚才得到的值上加50次就可以得到50-100之间的值.这个需要4次配合
    2-49之间的值几乎不可能,但是仍然有可能发生这种奇迹.
    首先让第一个线程取得sum=0,然后让第二个线程循环49次.接着用第一个线程运行到1-50之间的值,然后第二个线程取得这个值,接着第一个线程运行完,第二个线程在这个值的基础之上加1,于是就可以得到2-51之间的值.这个需要6次配合。
      

  4.   

    50-100之间的值比较好理解,我不再解释,关键是2-50之间的值如何被取到。
    我以极端的2为例子,说明这一点
    请看代码:
    package com;
    public class Threads extends Thread {   
    public static int sum = 0;   
    public static int state=2;
    public static Object obj=new Object();
    public boolean sub;//true为第一个线程,false为第二个线程
    /**     * @param args     */  
    public static void main(String[] args) {      
    Thread t1 = new Threads(true);    
    Thread t2 = new Threads(false);     
    t1.start();      
    t2.start();    
    while(state!=0){

    }
    System.out.println(sum);     
    }
    public Threads(boolean value){
    sub=value;
    }
    public void run() {     
    if(sub){
    for (int i = 1; i <= 50; i++) {  
    int value=sum;//取sum值
    if(i==1){
    try {
    Thread.sleep(100);//第一个线程取得0时等一会
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    sum=value+1;//sum值加1
    if(i==1){
    try {
    Thread.sleep(200);//第一个线程赋值为1时等待第二线程取到1时再运行
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    }else{
    try {
    Thread.sleep(1);//第二个线程延迟一会执行
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    for (int i = 1; i <= 50; i++) {  
    int value=sum;//取sum值
    if(i==50){
    try {
    Thread.sleep(250);//从第一个线程取得1之后等第一个线程运行完再执行加到2
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    sum=value+1;    //sum值加1
    if(i==49){
    try {
    Thread.sleep(150);//第一个循环完49次之后等一会
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    }
    synchronized(obj){
    state--;
    }
    }
    }
      

  5.   


    取值范围应该在 50~100 之间,主要是线程之间相互覆盖计算结果问题,最差也就相当于只跑了一次单线程的效果。不过因为循环太短了,估计还没等第二个线程启动第一个线程就已经运行结束,所以靠近100的概率很高。+1,run方法循环时间太短了,可能第二个还没开始,第一个就走完了,约100。。
      

  6.   


    看了一遍,觉得还是挺有道理的。仔细看了你的代码,其中有些存在异议的地方,探讨一下:
    其中int value=sum;这种写法相当于定义了一个临时变量保存了sum等于0时的状态,当线程2循环49次后可以从value这个临时变量中取得0;
    而题目中代码sum=sum+1;的这种写法,当线程2循环49次后其中标红的sum还有没有可能是0呢?
      

  7.   


    取值范围应该在 50~100 之间,主要是线程之间相互覆盖计算结果问题,最差也就相当于只跑了一次单线程的效果。不过因为循环太短了,估计还没等第二个线程启动第一个线程就已经运行结束,所以靠近100的概率很高。+1,run方法循环时间太短了,可能第二个还没开始,第一个就走完了,约100。。我觉得也是这样的
      

  8.   

    对于17楼的答案我有个疑问:
    这是Java:
    package com.test;public class Test {
    public static void main(String[] args) {
    int sum = 0;
    for(int i=0;i<10;i++) {
    sum = sum+1;
    }
    System.out.println(sum);
    }
    }
    这是对应的反汇编:
    D:\Code\WorkSpace_3.6\Test\bin\com\test>javap -c Test
    Compiled from "Test.java"
    public class com.test.Test extends java.lang.Object{
    public com.test.Test();
      Code:
       0:   aload_0
       1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
       4:   returnpublic static void main(java.lang.String[]);
      Code:
       0:   iconst_0
       1:   istore_1
       2:   iconst_0
       3:   istore_2
       4:   goto    13
       7:   iinc    1, 1
       10:  iinc    2, 1
       13:  iload_2
       14:  bipush  10
       16:  if_icmplt       7
       19:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
       22:  iload_1
       23:  invokevirtual   #22; //Method java/io/PrintStream.println:(I)V
       26:  return}
    可以从第7行看到, 对sum的+1操作,只用了一行,而在17楼的示意代码中,是先把sum的值取出来,然后运行线程2,再回过来用这个sum的值,所以对于这处,我还有一点疑问: 示意代码会不会破坏了原题的代码语义呢?
      

  9.   


    看了一遍,觉得还是挺有道理的。仔细看了你的代码,其中有些存在异议的地方,探讨一下:
    其中int value=sum;这种写法相当于定义了一个临时变量保存了sum等于0时的状态,当线程2循环49次后可以从value这个临时变量中取得0;
    而题目中代码sum=sum+1;的这种写法,当线程2循环49次后其中标红的sum还有没有可能是0呢?

    线程取sum值其实是临时地将值放在内存中,但是没有改变sum的值,这个和局部变量存储差不多,只是把过程分解容易控制而已,局部变量是线程内部的,完全模拟封装了虚拟机的栈.
      

  10.   

    能够猜到这个功能不是一个操作,要是一个整体结果肯定是100.
    你也可以写成int value=sum+1,sum=value;
    sum=sum+1;关键是取sum和赋值sum两个过程
      

  11.   

    能够猜到这个功能不是一个操作,要是一个整体结果肯定是100.
    你也可以写成int value=sum+1,sum=value;
    sum=sum+1;关键是取sum和赋值sum两个过程恩, 的确, 反编译带thread的code时, 取值与赋值是分开的操作.
    看来应该是局部变量与Thread里操作全局变量的不同导致的
           7: getfield      #14                 // Field sum:I
          10: iconst_1
          11: iadd
          12: putfield      #14                 // Field sum:I
      

  12.   

    public class Test {
      
    /**     * @param args     */   
    public static void main(String[] args) { 
     Test2 a=new Test2();
     Thread t1=new Thread(a);
     Test2 b=new Test2();
     Thread t2=new Thread(b);
     t1.start();
     t2.start();

    }

    }class Test2 implements Runnable{

    public static int sum = 0; 

    public void run() {
    // TODO Auto-generated method stub
    for(int i=1;i<=50;i++){
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    sum=sum+1;
    }
    System.out.println(sum);
    }

    }
    经过代码测试结果应该是100-200
      

  13.   

    0-100
    调用start并不一定线程就执行了.
      

  14.   

    sum = sum + 1 这个操作不是原子操作,这个加+1未必能够执行成功,所以取值范围是0-100