什麼是終止並行集合的最佳方式(在由其中一個線程引發的異常或由用戶發起的中斷的情況下)?GPars - 早期終止並行集合的正確方法
在任何一種情況下,我都可以輕鬆設置一些標誌並在循環的頂部檢查它。但是如果我在集合中有10,000個物品,我寧願告訴任何將這些物品送入ForkJoinPool以停止送入它們的物品。讓5或20個已經開始完成的物品,但不要再開始。
下面是一個示例,您可以插入以查看我的意思。如果我模擬其中一個線程拋出異常,看起來像集合停止處理,因爲線程計數的第一個打印(在'A:'消息)通常非常小(5左右)。但是,通過打印GParsPool.withPool外計數(在「B:」),我可以看到他們真的不停地運轉(總所有100):
void doIt() {
AtomicInteger threadCounter = new AtomicInteger(0)
AtomicInteger threadCounterEnd = new AtomicInteger(0)
try {
GParsPool.withPool { pool ->
try {
(1..100).eachParallel {
try {
if (threadCounter.incrementAndGet() == 1) {
throw new RuntimeException('planet blew up!')
}
// Do some long work
Integer counter=0
(1..1000000).each() {counter++}
// Flag if we went all the way through
threadCounterEnd.incrementAndGet()
} catch (Exception exc) {
//pool.shutdownNow()
throw new RuntimeException(exc)
}
}
} catch (Exception exc) {
println 'caught exception'
//pool.shutdownNow()
println "A: threads launched was ${threadCounter}, ended was ${threadCounterEnd}"
throw new RuntimeException(exc)
}
}
} catch (Exception exc) {
exc.printStackTrace()
}
println "B: threads launched was ${threadCounter}, ended was ${threadCounterEnd}"
}
如果我使用pool.shutdown()內eachParallel,它沒有任何影響。如果我使用pool.shutdownNow(),它會像我想要的那樣結束處理,但會拋出CancellationException,從而掩蓋了我想要的真正異常。我可以將「真正的」異常存儲在一個變量中供以後訪問,但是我不得不懷疑是否沒有更好的方法來告訴並行集合乾淨地停止。
謝謝,這證實了我的理解,至少。我確實希望在一項任務中發生異常會導致目前正在進行的並行執行 - 即結束當前的'每個並行'或其他任何(不一定像您指出的那樣是整個池,這對GPars來說是一個有風險的默認值)。只需確認 - shutdownNow是終止池的安全方式 - 它不像舊的Thread.stop那樣有風險,對吧?一如既往地感謝Vaclav,你通過回答這些問題做了很好的支持GPars的工作(希望這些問題也能幫助其他人)。 – user1373467
發佈了此解決方案的代碼示例以及相關問題:http://stackoverflow.com/questions/13771337/how-know-with-gpars-that-all-threads-have-finished-when-an-異常被拋出/ 13824965#13824965 – user1373467