public class ReaderResult extends Thread { 
    Calculator c;     public ReaderResult(Calculator c) { 
            this.c = c; 
    }     public void run() { 
            synchronized (c) { 
                    try { 
                            System.out.println(Thread.currentThread() + "等待计算结果"); 
                            c.wait(); 
                    } catch (InterruptedException e) { 
                            e.printStackTrace(); 
                    } 
                    System.out.println(Thread.currentThread() + "计算结果为:" + c.total); 
            } 
    }     public static void main(String[] args) { 
            Calculator calculator = new Calculator(); 
            //启动三个线程,分别获取计算结果 
            new ReaderResult(calculator).start(); 
            new ReaderResult(calculator).start(); 
            new ReaderResult(calculator).start(); 
            //启动计算线程 
            calculator.start(); 
            
    } 
}
public class Calculator extends Thread { 
    int total; 
    public void run() { 
            synchronized (this) { 
             System.out.println(total);
                    for (int i = 0; i < 101; i++) { 
                            total += i; 
                    } 
                    System.out.println(total);    
            } 
    } 
}
就2个简单的类 , 以我的认识,应该在c.wait()这里卡住,也就是说应该不会输出“计算结果为:" ”这些话。  但是为什么他有时候会输出呢?(有时候不会)。 到底是什么破坏了wait 状态?  应该不是start, 因为有时候是先输出System.out.println(total)这里, 然后再打印等待计算结果。。  高人请指点下 
多线程javathread

解决方案 »

  1.   

    1、wait是要和notify配对使用的,这里只看到wait却没有notify,这是一个问题
    2、没有notify的激活,照理说,是阻塞在wait这里的。
      

  2.   

    对象 c 做同步对象,同时这个c还是个线程对象,这样的设计就会导致这种结果。
    因为c.wait()会在c这个线程结束后,退出等待。
    (上面的 对象c在main里是叫 calculator).
    所以,楼主的代码如果如果calculator这个先结束,后运行的c.wait(),则程序就会一直停那;否则先运行c.wait(),calculator后结束,wait状态会在calculator结束后唤醒。我曾经写过一篇博客,楼主参考一下。
    http://blog.csdn.net/nmyangym/article/details/7850882
    楼主也可以看看jion()方法的原代码。
      

  3.   

    之前没有试过这个问题,刚刚搜了半天也没有答案……我搜的问题是: 如果你在一个 Thread 的 instance 上调用了 wait() 方法,跟其他普通的 Object 有什么不同……
    结果没搜到什么有价值的东西……我这么搜的原因是:
    如果你把你的 Calculator 实现改一改, 改成 implements Runnable 的话,你就会发现正常了。
    不过话说回来,wait notify 可以被认为是过时的机制,自从concurrent包之后,不要再用 wait notify 了,所以研究的意义可能也不大……要一个线程去等另一个线程,或者等某一个条件达成,concurrent包里有不好工具可以用,方法也不止一种(看情况用哪种),每一种都比 wait notify 好。
      

  4.   

    Mark一下,收藏起来!发现了是synchronized中是一个线程对象的问题,不知道为什么,看了2楼的回复,明白了。
      

  5.   


    public class ReaderResult extends Thread {
    Calculator c;
    public ReaderResult(Calculator c) {
    this.c = c;
    } public void run() {
    synchronized (this) {
    try {
    System.out.println(Thread.currentThread() + "等待计算结果");
    this.wait();
    } catch (Exception e) {
    e.printStackTrace();
    }
    c.start();
    System.out.println(Thread.currentThread() + "计算结果为:" + c.total);
    }
    } public static void main(String[] args) {
    Calculator calculator = new Calculator();
    Calculator calculator1 = new Calculator();
    Calculator calculator2 = new Calculator();
    // 启动三个线程,分别获取计算结果
    new ReaderResult(calculator).start();
    new ReaderResult(calculator1).start();
    new ReaderResult(calculator2).start();
    // 启动计算线程 }
    }
      

  6.   

    测试了下,大致几个情况:
    1、Calculator线程在执行run()函数结束后,会调用exit()方法;该方法执行完毕之后会发出一个notifyAll(),但没有找到对应代码,可能是在native代码中完成的;
    2、楼主所说“有时候是先输出System.out.println(total)这里, 然后再打印等待计算结果”
      是因为有的线程启动慢了(可以用循环来批量new ReaderResult(calculator).start(),比如100个,就会更明显);然后没有及时进入 synchronized (c) { 代码块,直到Calculator执行完毕才抢到c的独占权,所以最终卡在c.wait()而再也没机会唤醒了。
      

  7.   

    2楼,也改变了我对wait退出机制的一些认识!
      

  8.   

    +1  顺便顶下2楼是这样的,notifyAll是native实现的,这个倒不重要了。
      

  9.   

    你的synchronized锁定的全是同一个对象,所以会阻塞。那就是Calculator 的对象。
      

  10.   

    应该就是如2楼所说的问题了  在线程执行完毕之后也会结束WAIT状态的 ,  同时也谢谢别人的回答~