有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么要使用notify?

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

以下是我使用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++;
        }
    }
}

如果我执行notify调用,它仍然以相同的方式执行。也就是说,一旦锁被释放,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++;
            }
        }       
    }
}

无论通知是否存在,始终打印20000000

因此,据我所知,notify所做的唯一一件事可能是比需要的时间更早地唤醒线程,如果是这样的话,为什么要使用notify呢?为什么不等待锁被释放,让JVM重新启动另一个线程呢


共 (1) 个答案

  1. # 1 楼答案

    除非您或其他人调用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();
            }       
        }
    }
    

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

    编辑:我已经找到了一些关于这个的文档。从^{}

    As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.