2012-12-12 44 views
0

什麼是終止並行集合的最佳方式(在由其中一個線程引發的異常或由用戶發起的中斷的情況下)?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,從而掩蓋了我想要的真正異常。我可以將「真正的」異常存儲在一個變量中供以後訪問,但是我不得不懷疑是否沒有更好的方法來告訴並行集合乾淨地停止。

回答

2

ATM沒有這樣的機制。由於池無法區分您的任務和其他潛在計算的任務,因此它沒有任何機制來阻止線程讀取任務隊列。如果你知道你是線程池的唯一用戶,那麼你可以按照你的建議使用shutdownNow()(以上提到的結果)。

另一種選擇,我覺得你也知道,是直接在任務中正確捕捉異常,並設置共享原子標誌來指示其他任務立即退出。

+0

謝謝,這證實了我的理解,至少。我確實希望在一項任務中發生異常會導致目前正在進行的並行執行 - 即結束當前的'每個並行'或其他任何(不一定像您指出的那樣是整個池,這對GPars來說是一個有風險的默認值)。只需確認 - shutdownNow是終止池的安全方式 - 它不像舊的Thread.stop那樣有風險,對吧?一如既往地感謝Vaclav,你通過回答這些問題做了很好的支持GPars的工作(希望這些問題也能幫助其他人)。 – user1373467

+0

發佈了此解決方案的代碼示例以及相關問題:http://stackoverflow.com/questions/13771337/how-know-with-gpars-that-all-threads-have-finished-when-an-異常被拋出/ 13824965#13824965 – user1373467