2010-08-16 82 views
2

在對象構造函數中啓動線程池安全嗎?我知道你不應該從構造函數中啓動一個線程,關於「this」指針轉義(我不完全明白這一點,但會做一些更多的搜索嘗試找出它)。Java在對象構造函數中啓動線程池

的代碼會是這個樣子:

private ExecutorService pool; 

public handler() 
{ 
    pool = Executors.newCachedThreadPool(); 
} 

public void queueInstructionSet(InstructionSet set) 
{ 
    pool.submit(new Runnable that handles this instruction set); 
} 

如果不工作,我可以創建這個類作爲一個Runnable並在一個新的線程啓動它。然而,這似乎是在程序中增加了一個不必要的線程,而它並不真正需要它。

謝謝。

編輯:

感謝您的答覆大家,他們一定幫助理解這一點。

按照代碼,在我心中它是有道理的,這個構造函數創建的線程池,但讓我解釋一下具體是什麼這個代碼是幹什麼的,因爲我可以以一種不可思議的方式來思考這個問題。

這個對象的整個的一點是要採取相應的「指令集」對象,並採取行動。指令集來自連接到服務器的客戶端。一旦從客戶端接收到完整指令集,該指令集就被髮送到該對象(處理程序)進行處理。

此處理對象包含到每一個對象,該對象的指令集可根據作用的基準。它會將指令集提交給線程池,該線程池將查找該指令集想要與哪個對象進行交互,然後處理該對象上的指令集。

我能勝任在IO服務器的指令集的對象,但我的想法是有一個單獨的類它使整個代碼更易讀,因爲每個類是專注於做只有一個具體的東西。

想法?建議嗎?

感謝

回答

2

你的示例代碼不會讓「這個」逃跑的。在構造函數中啓動一個新線程是相當安全的(甚至可以使用this作爲Runnable,在本例中您不會這樣做),只要您確定已經將對象初始化到新線程將需要它。例如,設置了新的線程將靠後最後場啓動線程將是一個非常糟糕的主意:)

基本上讓「this」引用逃避一般討厭的,但不是普遍如此。有些情況下是安全的。小心一點。

說了這麼多,使得構造函數啓動一個線程可以被看作是在構造函數中做得太多。很難說在這種情況下是否合適 - 我們對代碼的功能不夠了解。

編輯:是啊,看了額外的信息,我認爲這是好的。你應該有一個關閉線程池的方法。

+0

謝謝,這有幫助。我用這個代碼特別做的更新了OP。我認爲讓構造函數創建線程池是有意義的,但我對此很新,並歡迎任何建議,我可以得到:) – vimalloc 2010-08-16 17:25:13

+0

@kyena:好的,編輯答案。基本上它看起來可能沒問題。你的班級有效*成爲一個線程池(通過組合)。 – 2010-08-16 17:29:40

+0

謝謝!我感謝幫助:) – vimalloc 2010-08-16 17:33:28

1

我同意喬恩。

此外,讓我指出你實際上並沒有在構造函數的線程池中開始任何動作。你正在實例化線程池,但它沒有任何任務要運行在這一點上。因此,正如所寫的,在完成構建之前,您不會有任何東西在這個實例上開始運行。

1

聽起來像線程池將被該對象擁有和使用;線程不會從對象中傳出。如果是這樣的話,這不應該是一個問題。

構造函數創建一個對象並初始化其狀態。我無法想象一個需要長時間運行的進程的用例。

我可以看到一個對象可能與一個線程池進行交互以完成一項任務,但我沒有看到該對象需要擁有該線程池。

更多詳細信息可能有幫助。

+0

謝謝,這有助於。我使用這段代碼特別針對線程池所做的更新了OP。我認爲讓這個對象擁有線程池是有意義的,但是我對此很新,並且歡迎任何我可以得到的建議:) – vimalloc 2010-08-16 17:25:58

0

我認爲只要該對象完全管理該線程池的生命週期,就可以在該對象的構造函數中啓動線程池。

如果你走這條路,你必須加倍努力,爲客戶提供以下擔保:

  1. 如果構造函數拋出任何異常(包括運行並檢查),您必須清理代碼在構造關閉線程池。如果你不這樣做並用非守護線程創建一個線程池,那麼例如,使用你的對象的一個​​小控制檯程序可能會永遠存在,從而泄漏寶貴的系統資源。
  2. 您需要提供一些我稱之爲destructor的方法,類似於Java I/O中的close。我通常稱它爲releaseResources。請注意0​​不是這個方法的替代品,因爲它被GC調用,而對於一個內存足夠小的對象,它可能永遠不會被調用。
  3. 當使用此對象遵循此模式

- >

MyThreadPoolContainer container = 
    new MyThreadPoolContainer(... args to initialize the object...); 

try 
{ 
    methodThatUsesContainer(container); 
} 
finally 
{ 
    container.releaseResources(); 
} 
  • 文獻該對象的構造分配有限的資源,所述destructor方法必須被明確地稱爲以防止其泄漏。