Java中的静态字段初始化

时间:2020-01-11 20:26:04

标签: java

我在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的静态字段初始化中有什么微妙之处吗?

非常感谢您。

1 个答案:

答案 0 :(得分:2)

LeetCode针对您的解决方案运行几个不同的测试用例。假设LeetCode在运行一个JVM并在该JVM中运行所有测试用例,但它为每种情况实例化了一个新的Foo

在运行第一种情况时,signal为零,并且您的代码按预期工作。但是在此测试用例signal的末尾现在是2,因为测试用例将其递增两次。由于它是静态的,因此它在Foo的所有实例之间共享。即使LeetCode为第二个测试用例实例化了一个新的Foo,静态的signal仍为2。first方法将其递增为3,但是由于条件{{ 1}}永远是正确的。

while (signal != 1)构造函数中将signal初始化为0具有在第二次和后续测试运行之前重置Foo的效果。

这里没有理由将signal设为静态。它应该是常规的非静态成员,以使signal的每个实例都获得一个初始化为零的新Foo

相关问题