在静态块中初始化线程?

时间:2013-04-19 01:50:22

标签: java multithreading static jvm

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

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

我之所以这样做是因为 我想从服务器检索数据,并且它需要花费太长时间才能获得它。因此,要保留我想要检索它的数据并将其存储在文件中,以便在客户端请求它时 - 它不需要调用服务器来获取信息。

2 个答案:

答案 0 :(得分:4)

  

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

嗯。是和否,没有。

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

  2. 如果您实际使用t.start()分叉线程,那么该线程将在后台运行,并且不会阻止类初始化。

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

  4. 如果您尝试将数据预先加载到程序中,那么您应该尽早在main()中运行加载部分,而不要将其停放在类中的static初始值设定项中。但是如果你在主线程中运行它,拿起程序,我不明白为什么这会比按需提出请求更快。

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

    类似的东西:

    public class DataLoader {
        private 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;
        }
    }
    

答案 1 :(得分:3)

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