在静态块中初始化线程?

4
如果我在静态块中启动一个线程,JVM会等待线程完成后再加载类吗?
static {
    System.out.println("static block");
    DataRetrievalThread t = new DataRetrievalThread();
    t.run();
}

我尝试这样做的原因是,我想从服务器检索数据,但获取数据的时间太长了。因此,为了使数据持久化,我想要检索并将其存储在文件中,这样当客户端请求数据时,就不需要再向服务器发起调用以获取信息。

2个回答

5
如果我在一个静态块中启动一个线程,那么 JVM 是否会在加载类之前等待该线程完成?
嗯,是的,也不是,还有不。
首先,您的代码没有分叉线程。因此,按照编写方式,它将阻止类构建,尽管严格来说,在static部分运行之前已“加载”类。这是因为您直接在当前主线程中执行run()方法。如果要分叉线程,则应调用 t.start() 。
如果使用t.start()实际上分叉出线程,则线程不会阻塞类初始化并在后台运行。
您真的不应该这样做。这是一种非常糟糕的模式。如果解释您要完成什么任务,我们就可以帮助您。
如果要预加载数据到程序中,则应在main()中尽早运行加载部分,而不是将其放置在类的static初始化器中。但是,如果在主线程中运行它并阻塞程序,则我不明白为什么这比按需进行请求更快。
考虑fork(使用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;
    }
}

4

使用run()方法可以在当前线程中执行代码,因此该类在此之后会完成加载。如果需要在新线程中运行该方法,则需要调用start()方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接