在我的一個Java 6應用程序中,我有一個線程向數據主線程提供數據,同時還從數據庫中預取更多記錄。它採用ArrayBlockingQueue隊列爲FIFO緩衝區,主循環是沿着這些路線的東西:當線程中斷時,BlockingQueue方法是否總是拋出InterruptedException?
while (!Thread.interrupted()) {
if (source.hasNext()) {
try {
queue.put(source.next())
} catch (InterruptedException e) {
break;
}
} else {
break;
}
}
有代碼,不會在循環後一點的清理結束,如中毒隊列並釋放任何資源,但這幾乎都是關於它的。
就目前而言,主線程到沒有直接通信:饋線線程:饋線線程被設置了適當的選項,然後自己離開,使用阻塞隊列來控制數據流。
當隊列滿時主線程需要關閉饋線時出現問題。由於沒有直接的控制通道,因此關閉方法使用接口接口interrupt()
饋線線程。不幸的是,在大多數情況下,饋線線程在put()
仍然被阻止,儘管被中斷 - 沒有任何例外。
通過對interrupt()
文檔和隊列實現源代碼的簡要介紹,在我看來,經常有put()
塊沒有使用任何JVM的可中斷設施。更具體地說,在我當前的JVM(OpenJDK 1.6b22)上,它阻塞了sun.misc.Unsafe.park()
本地方法。也許它使用自旋鎖或其他東西,但無論如何,這似乎落在the following case:
如果以前的任何條件都不成立,則會設置此線程的中斷狀態。
一個狀態標誌設置,但線程仍然受阻於put()
,並且不進一步遍歷而標誌進行檢查。結果?一個殭屍線程只是不會死!
我對這個問題的理解是正確的,還是我錯過了什麼?
解決此問題的可能方法是什麼?現在我只能想到兩種解決方案:
a。調用
poll()
一堆隊列上的疏通進紙器線程:醜陋和不是很可靠,從我所見過的,但它主要是作品。b。使用
offer()
方法用超時而不是put()
來允許線程在可接受的時間範圍內檢查其中斷狀態。
除非我遺漏了一些東西,否則這是對Java中BlockingQueue實現的一個有點沒有記錄的警告。有似乎是它的一些跡象,當文件例如建議中毒隊列以關閉工作線程,但我找不到任何明確的參考。
編輯:
行,還有一個更,恩,急劇的上述溶液(a)的變化:ArrayBlockingQueue.clear()
。我認爲這應該始終工作,即使它不完全是優雅的定義...
我輕輕地拋棄了這種可能性,因爲饋線線程花費更多的時間在等待'把()'。然而這聽起來似乎合理。 'source'對象屬於第三方數據庫相關的庫 - 所有那些網絡代碼,*有*是一個拋出的InterruptedException,但頂級方法不會拋出它們......嘆氣,我*討厭*挖掘第三方代碼... – thkala 2012-02-13 01:09:54
哦,大聲哭泣......誰寫這個庫,它吞下每一個拋出的InterruptedException!每一個!誰寫這樣的代碼? – thkala 2012-02-13 01:22:22
順便說一下,將線程狀態設置爲中斷,只要該特定線程處於關閉狀態,就不會改變任何內容 - 一旦環路將線路直接切斷到終止狀態。我沒有得到任何例外處理,無論如何... – thkala 2012-02-13 01:30:42