我在LeetCode上做题时遇到了这个问题:https://leetcode.com/problems/print-in-order/
考虑两个提交:
1.
class Foo {
private static int signal = 0;
public Foo() {}
public synchronized void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
signal += 1;
notifyAll();
}
public synchronized void second(Runnable printSecond) throws InterruptedException {
while(signal != 1)
wait();
// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
signal += 1;
notifyAll();
}
public synchronized void third(Runnable printThird) throws InterruptedException {
while(signal != 2)
wait();
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
notifyAll();
}
}
2.
class Foo {
private static int signal = 0;
public Foo() {signal = 0;}
public synchronized void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
signal += 1;
notifyAll();
}
public synchronized void second(Runnable printSecond) throws InterruptedException {
while(signal != 1)
wait();
// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
signal += 1;
notifyAll();
}
public synchronized void third(Runnable printThird) throws InterruptedException {
while(signal != 2)
wait();
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
notifyAll();
}
}
尝试提交这两项,您会发现提交 1 将导致超出时间限制,而提交 2 将被接受。
唯一的区别是,在提交2中,我显式添加了一条语句signal = 0;
来初始化静态变量。它应该没有什么区别,因为我已经在 private static int signal = 0;
中给了这个变量一个默认值,所以这里发生了什么。 Java中的静态字段初始化有什么我不知道的微妙之处吗?
非常感谢。
最佳答案
LeetCode 针对您的解决方案运行多个不同的测试用例。我们假设 LeetCode 运行单个 JVM 并运行该 JVM 中的所有测试用例,但它为每个用例实例化一个新的 Foo
。
运行第一个案例时,signal
为零,并且您的代码按预期工作。但在此测试用例结束时,signal
现在为 2,因为测试用例将其递增了两次。由于它是静态的,因此它在 Foo 的所有实例之间共享。即使 LeetCode 为第二个测试用例实例化了一个新的 Foo
,静态 signal
仍然是 2。first
方法将其增加到 3,但是然后测试挂起,因为条件 while (signal != 1)
始终为 true。
在 Foo
构造函数中将 signal
初始化为 0 可以在第二次及后续测试运行之前重置 signal
。
没有理由将 signal
设为静态。它应该是一个常规的非静态成员,以便 Foo
的每个实例都会获得一个初始化为零的新signal
。
关于java - Java中的静态字段初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59698370/