【问题标题】:Initializing a thread in a static block?在静态块中初始化线程?
【发布时间】:2013-04-19 01:50:22
【问题描述】:

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

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

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

【问题讨论】:

    标签: java multithreading static jvm


    【解决方案1】:

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

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

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

    2. 如果你真的用t.start() fork 线程,那么不,线程将在后台运行,不会阻止类初始化。

    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;
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2011-01-26
        • 2013-09-03
        • 1970-01-01
        • 2011-11-17
        • 1970-01-01
        • 2016-09-12
        • 2011-01-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多