2013-04-19 100 views
2

如果我在一個靜態塊中啓動一個線程。 jvm會在加載類之前等待線程完成嗎?初始化靜態塊中的線程?

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

的原因,我想這是因爲 我想從服務器獲取數據,它的服用時間太長得到它。因此,要保留要檢索的數據並將其存儲在一個文件中,以便客戶端請求時 - 不需要調用服務器來獲取信息。

回答

4

如果我在一個靜態塊中啓動一個線程。 jvm會在加載類之前等待線程完成嗎?

呃。是,否,不。

  1. 首先,您的代碼不是分叉線程。因此,它被寫入舉行類建設,雖然技術上該類是在「static」部分運行之前「加載」。這是因爲您正在當前主線程中直接執行run()方法。如果你想分叉線程,那麼你應該撥打t.start();

  2. 如果你實際上將線程與t.start()分開,那麼no,線程將在後臺運行並且不會阻塞類的初始化。

  3. 你真的應該不是做這樣的事情。這是一個非常糟糕的模式。如果你解釋你正在努力完成什麼,我們應該能夠真的幫助

如果你正在嘗試將數據加載預到你的程序,那麼你只應該早在main()運行負荷部分,在一個類中的static初始化不停放。但是,如果你在主線程中運行它,舉起程序,我不明白爲什麼這麼做會比按需提出請求更快。

需要考慮的一件事是分叉(用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; 
    } 
} 
+0

添加了一些代碼@ 12rad。 – Gray

3

With run()您在當前線程中執行該方法,因此在該類之後該類將完成加載。您需要致電start()以在新線程中運行該方法。