4

如果我在静态块中启动一个线程。jvm会在加载类之前等待线程完成吗?

static {
    System.out.println("static block");
    DataRetrievalThread t = new DataRetrievalThread();
    t.run();
}

我尝试这样做的原因是因为我想从服务器检索数据并且获取它的时间太长了。因此,为了持久化我想要检索的数据并将其存储在一个文件中,这样当客户端要求它时 - 它不需要调用服务器来获取信息。

4

2 回答 2

5

如果我在静态块中启动一个线程。jvm会在加载类之前等待线程完成吗?

呃。是的,不是的,不是的。

  1. 首先,您的代码不是分叉线程。因此,尽管从技术上讲,该类在该部分运行之前已“加载”,但正如它所写的那样,它将支持类构造。static那是因为您run()直接在当前主线程中执行该方法。如果你想分叉线程,那么你应该调用t.start();.

  2. 如果你真的用t.start()then no 分叉线程,线程将在后台运行并且不会阻止类初始化。

  3. 你真的应该做这样的事情。这是一个非常糟糕的模式。如果您解释您要完成的工作,我们应该能够提供真正的帮助。

如果您尝试将数据预加载到您的程序中,那么您应该尽早运行加载部分main()并且不要将其停放在static类的初始化程序中。但是如果你在主线程中运行它,阻止程序,我不明白为什么这比按需发出请求更快。

要考虑的一件事是分叉(使用t.start())一个后台线程来加载数据,然后拥有一个保存数据的类。如果线程及时完成,那么它将预先加载数据。当程序需要数据时,它应该调用类来获取它。如果线程尚未完成,它可以执行countDownLatch.await(). 当线程完成下载它可以做countDownLatch.countDown()。所以你会得到一些并行性。

就像是:

public class DataLoader {
    private volatile Stuff data;
    private final CountDownLatch latch = new CountDownLatch(1);
    // start the thread, called early in main()
    public void init() {
        // you pass in this so it can call setData
        DataRetrievalThread t = new DataRetrievalThread(this);
        t.start();
    }
    // called from the DataRetrievalThread
    public void setData(Stuff data) {
        this.data = data;
        latch.countDown();
    }
    public Stuff getData() {
        if (data == null) {
            latch.await();
        }
        return data;
    }
}
于 2013-04-19T01:57:27.237 回答
4

随着run()您在当前线程中执行该方法,之后该类将完成加载。您需要调用start()以在新线程中运行该方法。

于 2013-04-19T01:56:30.153 回答