是否在线程结束时发出通知?为什么这个代码示例有效?

时间:2012-07-23 09:10:10

标签: java multithreading concurrency wait notify

我正在寻找线程的一些难题,我无法弄清楚为什么以下一直打印999999

class Job extends Thread {  
    private Integer number = 0;  
    public void run() {  
        for (int i = 1; i < 1000000; i++) {  
            number++;  
        }  
    }  
    public Integer getNumber() {  
        return number;  
    }  
}  
public class Test {  
    public static void main(String[] args)   
    throws InterruptedException {  
        Job thread = new Job();  
        thread.start(); 
        synchronized (thread) {  
            thread.wait();  
        }  
        System.out.println(thread.getNumber());  
    }  
}   

同一个锁上没有notify(虚假的唤醒似乎被忽略了) 如果一个线程完成,则通知获取信号或什么? 为什么main会打印结果而不会“卡住”等待?

6 个答案:

答案 0 :(得分:13)

在Javadoc for Java 7 Thread.join(long)

  

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

直接使用线程这种方式被认为是不实际的。注意:wait()可能因任何原因而结束,可能是虚假的。


基于与@Voo评论相关的益智游戏。关键是你不应该使用Thread的内部行为,因为这更容易导致混淆。

public static String getName() {
    return "MyProgram";
}
public static void main(String... args) {
    new Thread() {
       public void run() {
           System.out.println("My program is " + getName());
        }
    }.start();
}

该程序打印什么?

答案 1 :(得分:3)

为了澄清,我已将您的代码修改为:

Job thread = new Job();
thread.start();
final Object lock = new Object();
synchronized (lock) { lock.wait(); }
System.out.println(thread.getNumber());

现在它阻止了。这是@Nitram在他的回答中解释的第一手确认。如果你在Thread实施代码中care to have a look,那么为什么这是观察到的行为就很明显了。

答案 2 :(得分:3)

注意:此答案已经过广泛编辑。


这种行为的原因是,“某人”在内部调用notifyAll。这个“某人”是JVM本身,你可以在这里看到C源:

http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/f95d63e2154a/src/share/vm/runtime/thread.cpp

在第1531行中,方法ensure_join调用notifyAll。这与wait中的java.lang.Thread#join来电相对应(正如Marko和其他人所述)。

ensure_join依次在方法JavaThread::exit的第1664行中调用。


由于这是“内部记账”,没有人应该依赖这种行为。

答案 3 :(得分:2)

简单地说,一旦线程执行结束,Thread就会通知所有等待的线程。它不是建议为什么这样做,但它的工作原理。要在线程结束时进行同步,请使用Thread.join

答案 4 :(得分:0)

线程完成后会自动通知线程对象,这就是主线程不会卡住的原因。

答案 5 :(得分:-1)

嗯....通知用于过早通知等待锁定对象的线程。如果您不使用Notify,那么当它完成时它会释放锁定。

So that is equivalent to notify

不,不是。考虑下面的情况。

class Job extends Thread {  
    private Integer number = 0;  
    public void run() {

       synchronized(this) {
       for (int i = 1; i < 1000000; i++) {  
            number++;  
        }  
        notify();     //releases lock here and your main thread continues
        do sumthing...
        do sumthing...
        }  
    }
    public Integer getNumber() {  
        return number;  
    }  
}  

如果你不使用notify()...只有在你做完所有的总结之后才会释放锁..

相关问题