爲了使用多線程返工一個服務方法後,我發現,如果多個用戶試圖請求頁面(和調用服務方法)很多次,服務器開始拋出「不能得到連接池已用盡「異常。讓我舉一個我的服務班的例子。Grails。不能得到一個連接,池耗盡
class DocumentService {
def convertToJSON() {
docs.collect { doc ->
taskExecutor.submit({
Document.withNewSession {
def json = convertDocumentToJSON(doc)
}
} as Callable)
}.collect { it.get() }
}
def convertDocumentToJSON(doc){
def json = [:]
// ... fill json with data using doc and GORM requests
evaluateStatus(json)
return json
}
def evaluateStatus(json){
//... some work using database through GORM
}
}
我一直在努力解決這個問題超過一週,我找不到解決方案。我不太清楚Grails是如何處理會話,連接和事務的。我的猜測是跟隨。當convertDocumentToJSON被調用時,它需要從連接池(4個用戶,每個用戶25個線程= 100個連接),但這時就需要調用evaluateStatus方法,該方法還嘗試獲取從池中它自己的需要連接。但池已經耗盡,沒有一個線程可以釋放連接,因爲它們都在等待evaluateStatus。所以,存在僵局。我試圖爲evaluateStatus放置SUPPORT傳播類型,但我得到「池連接已關閉」異常。後來我想,如果我擺脫convertDocumentToJSON evaluateStatus調用它可能工作,並寫了這樣的代碼
def convertToJSON(){
docs.collect { doc ->
taskExecutor.submit({
Document.withNewSession {
def json = convertDocumentToJSON(doc)
evaluateStatus(json) // move call from convertDocumentToJSON
}
} as Callable)
}.collect { it.get() }
}
但在這種情況下,我也面臨着同樣的錯誤(用盡池)。請給我建議我應該在我的代碼修復
謝謝。是的,我嘗試使用GPars,但它僅適用於ForkJoinPool。我實際上並不記得是什麼問題,但它不符合我的期望。我真的很好奇 – volea
以上的代碼有什麼問題taskExecutor是一個Java ExecutorService嗎?如果有的話,它創建的游泳池有多大? –
是的,它是ExecutorService。池大小爲30.連接池 - 100 – volea