下面的类定义在一个文件里:
class Honey {
 
    private int honey= 0;
   
    public synchronized void setHoney(int honey) {
        this.honey = honey;
    }
   
    public synchronized int getHoney() {
        return honey;
    }
   
}
 
class Bee extends Thread {
    Honey honey;
    public Client(Honey honey) {
        this.honey = honey;
    }
    public void run() {
        for (int i = 1; i <= 1000; i++) {
            honey.setHoney(honey.gethoney() + 1);
 
        }
    }
}
 
public class RunTest {
    public static void main(String[] args) throws Exception {
        Honey honey = new Honey();
        Bee bee1 = new Bee(honey);
        Bee bee2 = new Bee(honey);
        bee1.start();
        bee2.start();
        bee1.join();
        bee2.join();
    }
}问最后honey的结果是不是2000,如果不是,应该如何改进?
在回答这个问题之前,我有两个疑问,第一个是,他说所有的类都在一个文件里,是什么意思?第二个问题是,class Bee里面的Client方法是不是写错了?

解决方案 »

  1.   

     Honey honey;
      public Client(Honey honey) {
      this.honey = honey;
      }
    你说出错的地方是这里吗 这个好像定义了一个类变量吧 没有错
      

  2.   

    类是Bee,构造函数是Client,是不是有问题啊?
      

  3.   


    错了吧 如果不是构造函数的话是应该有返回类型的 比如 void 或者 String 等等但是这个明显是个构造函数,在Bee类里面构造Client  没见过
      

  4.   

    我的问题是这个程序的结果最后能否保证是2000?
    我在这边运行了好多次,只有一次最后是2000,我在Bee类里加了System.out.println(honey.getHoney());
    class Bee extends Thread {
      Honey honey;
      public Client(Honey honey) {
      this.honey = honey;
      }
      public void run() {
      for (int i = 1; i <= 1000; i++) {
      honey.setHoney(honey.gethoney() + 1);
      System.out.println(honey.getHoney());
      }
      }
    }
    只有一次结果是2000,请问怎么修改
      

  5.   

    大哥, 在操作honey里,先把honey锁上。
      

  6.   


    我调用honey.getHoney()的时候,这个getHoney已经是锁的
      

  7.   

    弱弱的问下干嘛要加上synchronized,不是已经有join啦
      

  8.   

    程序修改完成!两个线程执行完毕后就是2000,没有问题!package com.test.t0917;class Honey { private int honey = 0; public synchronized void setHoney(int honey) {
    this.honey = honey;
    } public synchronized int getHoney() {
    return honey;
    }}class Bee extends Thread {
    Honey honey; public Bee(Honey honey) {
    this.honey = honey;
    } public void run() {
    for (int i = 1; i <= 1000; i++) {
    honey.setHoney(honey.getHoney() + 1); }
    }
    }public class Test1 {
    public static void main(String[] args) throws Exception {
    Honey honey = new Honey();
    Bee bee1 = new Bee(honey);
    Bee bee2 = new Bee(honey);
    bee1.start();
    bee2.start();
    bee1.join();
    bee2.join();
    System.out.println(honey.getHoney());
    }
    }
      

  9.   

       想问下,
      public Client(Honey honey) {
      this.honey = honey;
      }
       这个地方没有错么?为什么这样定义啊?API文档上面都没有如此定义过啊学习了望解答!
      

  10.   

    那后面这个构造函数哪里来的?
      Bee bee1 = new Bee(honey);
      Bee bee2 = new Bee(honey);
      

  11.   


    我copy你的代码,直接运行,结果是1398,不是2000
      

  12.   

        public void run() {
            for (int i = 1; i <= 1000; i++) {
                synchronized (honey) {
                    honey.setHoney(honey.getHoney() + 1);
                }
            }
        }
      

  13.   

    现在结果是2000,但是为什么啊?
    在honey类里,那两个方法全都是synchronized,任何一个thread调用了任何一个方法,别的thread都无法调用这个类里的其他方法,换句话说,互斥已经提供了,但是为什么还要加上synchronized (honey)?
      

  14.   

    我修改了下代码,如下:
    class Honey {
     
      private int honey= 0;
       
      public synchronized void setHoney(int honey) {
      this.honey = honey;
      }
       
      public synchronized int getHoney() {
      return honey;
      }
      public void print()
      {
      System.out.println("honey: "+honey);
      }
    }
     
    class Bee extends Thread {
    // class Bee {
      Honey honey;
      public Bee(Honey honey) {
      this.honey = honey;
      }
      public void run() {
      for (int i = 1; i <= 1000; i++) {
      honey.setHoney(honey.getHoney() + 1);
     
      }
      }
    }
     
    public class Test {
      public static void main(String[] args) throws Exception {
      Honey honey = new Honey();
      Bee bee1 = new Bee(honey);
      Bee bee2 = new Bee(honey);
      bee1.run();
      bee2.run();
      
      bee1.start();
      bee2.start();
      bee1.join();
      bee2.join();
      honey.print();
      }
    }
    奇怪的是每次结果都是4000...神奇...
      

  15.   

    此外,我还试过,如果不用多线程,将extends Thread注释掉的话结果是2000无误
      

  16.   

    honey.setHoney(honey.getHoney() + 1)
    应该相当于
    int temp = honey.getHoney()+1;
    honey.setHoney(temp);getHoney和setHoney都是同步的,但是并不一定一起执行的
    可能出现这样的情况
    bee1:getHoney
    bee2:getHoney
    bee2:setHoney
    bee1:setHoney于是,这两次操作的结果就只增加了1个人理解
      

  17.   

    额,发现忘记注释测试代码了,将两个.run();注释掉后结果正确,每次都是2000,此外在我的eclipse中,run()内锁不锁Honey结果都完全相同.都是2000无误,代码如下
    class Honey { private int honey= 0; public synchronized void setHoney(int honey) {
    this.honey = honey;
    } public synchronized int getHoney() {
    return honey;
    }
    public void print()
    {
    System.out.println("honey: "+honey);
    }
    }class Bee extends Thread {
    // class Bee {
    Honey honey;
    public Bee(Honey honey) {
    this.honey = honey;
    }
    public void run() {
    for (int i = 1; i <= 1000; i++) {
    // synchronized (honey) {
    honey.setHoney(honey.getHoney() + 1);
    // }
    }
    }}public class Test {
    public static void main(String[] args) throws Exception {
    Honey honey = new Honey();
    Bee bee1 = new Bee(honey);
    Bee bee2 = new Bee(honey); bee1.start();
    bee2.start();
    bee1.join();
    bee2.join();
    honey.print();
    }
    }
      

  18.   

    ...不会是eclipse的问题吧,自动保护线程?谁测试出不是2000?用的是什么环境?
      

  19.   


    你可以尝试下每次set的时候honey的值,看下是否有这种情况
    如果用lz原本的代码的话(要修bug= =),基本跑不出2000的
      

  20.   


    结果肯定是4000,因为Honey只有一个对象 Honey honey = new Honey();
    Bee bee1 = new Bee(honey);
    Bee bee2 = new Bee(honey);
    bee1.run();//这里处理后,honey变成2000
    bee2.run();//honey的值为2000,这里再处理后,就变成4000 bee1.start();
    bee2.start();
      

  21.   

    你说错了...不过那个问题我自己发现了,那两个run()是忘记注释掉的测试代码,问题是我跑LZ的程序每次都是2000?
      

  22.   

    class Honey { private int honey = 0; public synchronized void setHoney(int honey) {
    this.honey = honey;
    } public synchronized int getHoney() {
    return honey;
    }
    public int getHoneyValue(){

    return this.honey;

    }}class Bee extends Thread {
    Honey honey;

    public Bee(Honey honey) {
    this.honey = honey;
    } public void run() {
    for (int i = 1; i <= 1000; i++) {
    synchronized(honey){
    honey.setHoney(honey.getHoney() + 1);
    } }
    }
    }public class RunTest {

    public static void main(String[] args) throws Exception {
    Honey honey = new Honey();
    Bee bee1 = new Bee(honey);
    Bee bee2 = new Bee(honey);
    bee1.start();
    bee2.start();
    bee1.join();
    bee2.join();
    System.out.println(honey.getHoneyValue());
    }
    }
    让两个线程交替执行就可以啦!!!!!!
    我测试一直都是2000
    楼主如果有测试不对的可以发信息到QQ:997263515
    一起交流,,,同时本人广交天下好友
      

  23.   

    老师诚不欺我啊,发现问题所在了,公司电脑的CUP太好了...运算太快,完全不出现上述问题,在get和set间加入print终于得到非2000的结果了...
      

  24.   

    31楼可以试试我修改的测试代码:
    class Honey { private int honey= 0; public synchronized void setHoney(int honey) {
    this.honey = honey;
    } public synchronized int getHoney() {
    return honey;
    }
    public void print()
    {
    System.out.println("honey: "+honey);
    }
    }class Bee extends Thread {
    // class Bee {
    int num;
    Honey honey;
    public Bee(Honey honey,int num) {
    this.honey = honey;
    this.num=num;
    }
    public void run() {
    for (int i = 1; i <= 1000; i++) {
    // synchronized (honey) {
    int tmp=honey.getHoney() + 1;
    System.out.println("bee"+num+" get");
    honey.setHoney(tmp);
    System.out.println("bee"+num+" set");
    // honey.setHoney(honey.getHoney() + 1);
    // }
    }
    }}public class Test {
    public static void main(String[] args) throws Exception {
    Honey honey = new Honey();
    Bee bee1 = new Bee(honey,1);
    Bee bee2 = new Bee(honey,2);
    bee1.start();
    bee2.start();
    bee1.join();
    bee2.join();
    honey.print();
    }
    }
      

  25.   

    其中的代码:
    private int honey= 0;
    Honey honey = new Honey();
    请问honey既是对象又是变量吗?
      

  26.   

    完全不是一个概念,private int honey= 0;,这个是类成员声明,Honey honey = new Honey();,这个是main()函数内声明并初始化Honey类.建议36楼的同学去看java基础教程...
      

  27.   

    此外,楼主可以结帖了,的确是要在get和set执行时锁住,让get和set在同一线程内同时执行,否则出现结果小于2000的问题,至于部分人不锁也出现2000,那个是因为CPU运行太快...可以考虑sleep一下,或加入其它语句,就可以看出多线程的现象了.
    我的最终代码:
    class Honey { private int honey= 0; public synchronized void setHoney(int honey) {
    this.honey = honey;
    } public synchronized int getHoney() {
    return honey;
    }
    public void print()
    {
    System.out.println("honey: "+honey);
    }
    }class Bee extends Thread {
    // class Bee {
    int num;
    Honey honey;
    public Bee(Honey honey,int num) {
    this.honey = honey;
    this.num=num;
    }
    public void run() {
    for (int i = 1; i <= 1000; i++) {
    synchronized (honey) {
    int tmp=honey.getHoney() + 1;
    System.out.println("bee"+num+" get");
    honey.setHoney(tmp);
    System.out.println("bee"+num+" set");
    // honey.setHoney(honey.getHoney() + 1);
    }
    }
    }}public class Test {
    public static void main(String[] args) throws Exception {
    Honey honey = new Honey();
    Bee bee1 = new Bee(honey,1);
    Bee bee2 = new Bee(honey,2);
    bee1.start();
    bee2.start();
    bee1.join();
    bee2.join();
    honey.print();
    }
    }
      

  28.   

    private int honey= 0;改成private static int honey= 0;
    保证两个线程对一个共享变量进行访问;
    否则是产生了两个honey,哪杨结果应该是1000
      

  29.   

    你这样的锁法不行.
    你只锁了读和写,应该是读写一块儿锁.
    我给你举个流程例子:
    honey=1
    A读=1
    B读=1
    A写=2
    B写=2
    这样你不就少了1吗?