我正在寻找线程的一些难题,我无法弄清楚为什么以下一直打印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
会打印结果而不会“卡住”等待?
答案 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()...只有在你做完所有的总结之后才会释放锁..