我为什么要使用通知?

时间:2011-10-04 17:25:21

标签: java multithreading

我正在阅读我的SCJP书,我正在关于线程的章节,我想知道为什么你应该使用通知。

以下是我使用notify的示例程序:

class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();
        b.start();

        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();
            }catch(InterruptedException e) {}
            System.out.println("Total is: " + b.total);
        }
    }
}

class ThreadB extends Thread {
    int total;
    public void run() {
        synchronized(this) {
            for(int i = 0; i < 100000000; i++){
                total++;
            }
            notify();
        }       
        for(int i = 0; i < 100000000; i++){
            total++;
        }
    }
}

如果我取消通知电话,它仍然以相同的方式执行。 I.E.,一旦锁被释放,b.wait()最终会停止阻塞,我们得到一个介于100000000和200000000之间的半随机数,具体取决于调度程序。

此代码:

class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();
        b.start();

        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();
            }catch(InterruptedException e) {}
            System.out.println("Total is: " + b.total);
        }
    }
}

class ThreadB extends Thread {
    int total;
    public void run() {
        synchronized(this) {
            for(int i = 0; i < 100000000; i++){
                total++;
            }
            notify();
        }       
    }
}

无论通知是否存在,始终会导致打印100000000。

这段代码:

class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();
        b.start();

        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();
            }catch(InterruptedException e) {}
            System.out.println("Total is: " + b.total);
        }
    }
}

class ThreadB extends Thread {
    int total;
    public void run() {
        synchronized(this) {
            for(int i = 0; i < 100000000; i++){
                total++;
            }
            notify();
            for(int i = 0; i < 100000000; i++){
                total++;
            }
        }       
    }
}

无论通知是否存在,始终打印出200000000。

据我所知,通知所做的唯一事情可能是早于需要唤醒线程,如果是这样的话,为什么要使用notify呢?为什么不等待释放锁并让JVM重新启动另一个线程?

1 个答案:

答案 0 :(得分:3)

除非您或其他人致电notify(),否则wait() 应该永远继续,除非是虚假的醒来。你确定什么都没有打断线程吗?

基本上你精确地使用notify()来唤醒线程。如果您不需要让线程进入休眠状态,直到另一个线程可以通知它应该唤醒它,请不要使用它。

编辑:好的,我已经重现了这种行为 - 我怀疑这是因为你在线程对象本身上调用了wait()。我的猜测是,当线程终止时,Thread对象会收到通知。

尝试等待共享的Object,如下所示:

class ThreadA {

    static Object monitor = new Object();

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

        synchronized(monitor) {
            try {
                System.out.println("Waiting for b to complete...");
                monitor.wait();
            }catch(InterruptedException e) {}
            System.out.println("Total is: " + b.total);
        }
    }
}

class ThreadB extends Thread {
    int total;
    public void run() {

        synchronized(ThreadA.monitor) {
            for (int i = 0; i < 100000000; i++) {
                total++;
            }
//            ThreadA.monitor.notify();
        }       
    }
}

如果取消注释该行,程序将终止 - 否则不会。

编辑:我实际上已经找到了一些关于此的文档。来自Thread.join(millis, nanos)

  

当一个线程终止时,将调用this.notifyAll方法。建议应用程序不要在Thread实例上使用wait,notify或notifyAll。