为什么多线程等待和唤醒报错 不成功呢

package jack;


public class ThreadA {

    private static Object lock = new Object();
    private static Object lock1 = new Object();

    public static void main(String[] args) {
        ThreadB threadB = new ThreadB(lock);
        
        threadB.start();

        System.out.println("threadB is Start.....");
        synchronized (lock1) {
            ThreadC threadC = new ThreadC(lock);
            threadC.start();

            /* try { */
            System.out.println("Waiting for b to complete...");

            /* threadB.wait(); */

            /*
             * } catch (InterruptedException e) { // TODO Auto-generated catch
             * block }
             */
            System.out.println("Total is :" + threadB.total);

        }

    }
}

class ThreadB extends Thread {

    Object object;
    ThreadB(Object object)
    {
        this.object=object;
    }
    int total = 0;

    public void run() {
        // TODO Auto-generated method stub
        synchronized (object) {
            System.out.println("ThreadB is running..");
            for (int i = 0; i < 100; i++) {
                total += i;
                System.out.println("total is " + total);

                if (i == 50) {
                    try {

                        this.wait();
                    } catch (InterruptedException e) {
                    }
                }
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                }
            }
        }

    }
}

class ThreadC extends Thread {
    Object obj = null;

    ThreadC(Object obj) {
        this.obj=obj;
    }

    int total = 0;

    public void run() {
        // TODO Auto-generated method stub
        synchronized (obj) {
            System.out.println("ThreadC is running..");
            for (int i = 0; i < 100; i++) {
                total += i;
                System.out.println("TOTAL_C is " + total);
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                }
            }
            notify();
        }

    }
}

 

你同一个题目不用问两次吧。

把ThreadB类中的this.wait(); 改成 object.wait();
把ThreadC类中的notify(); 改成 object.notify();

这样就可以了。

原因是这样的,虽然wait是用来使当前线程阻塞并放弃锁,notify是用来唤醒阻塞线程。所以很多人自然而然的觉得应该用线程来调用wait/notify方法。

其实Thread类中是没有wait/notify方法的,只有Object中有。我们可以看看Object中wait()方法的API解释:

public final void wait() throws InterruptedException
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。换句话说,此方法的行为就好像它仅执行 wait(0) 调用一样。
当前线程必须拥有此[color=red]对象监视器[/color]。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。

对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用: 

[color=red]synchronized (obj)[/color] {
while ()
[color=red]obj.wait();[/color]
... // Perform action appropriate to condition
}
此方法只应由作为此对象监视器的所有者的线程来调用。

抛出:
[color=red]IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。 [/color]
InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,任何线程中断了当前线程。在抛出此异常时,当前线程的中断状态 被清除。

对象监视器指的是synchronized (obj)块的obj,也就是线程同步操作的公共区对象。想让一个线程等待,首先必须这个线程已经获得了对象监视器的锁。或者说已经在执行synchronized 块中的代码了,这时调用对象监视器的wait方法,才能够使得获得此对象监视器的线程等待,而不是直接用线程调用wait()方法。

当然,至于为什么this.wait()编译不报错,因为任何类都是Obeject的子类,所以都有wait()方法,但是this对象却不一定当前都占有了锁的。