在静态块中初始化线程?

12r*_*rad 3 java static multithreading jvm

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

static {
    System.out.println("static block");
    DataRetrievalThread t = new DataRetrievalThread();
    t.run();
}
Run Code Online (Sandbox Code Playgroud)

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

Gra*_*ray 5

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

呃。是和否和否。

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

  2. 如果你真的 fork 线程t.start()然后 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;
    }
}
Run Code Online (Sandbox Code Playgroud)