0
  1. 我有一個需要在for循環中處理的40000條記錄的列表。由於我有一個雙處理器系統。我創建了一個fixedThreadPool這樣的:ExecuterService停止處理兩個線程中的一個線程

    int threads = Runtime.getRuntime().availableProcessors(); ExecutorService service = Executors.newFixedThreadPool(threads);

  2. ,分我ArrayList成兩個子列表。對於這些子列表中的每一個,我創建了一個執行相同功能的Callable(包括迭代子列表並執行一些處理),並返回一個Future對象。

  3. 我提出這兩個Callable使用executorServiceObject.submit(callable)並添加返回Future對象到我Future對象

下面的列表是我的問題:

我已經寫了System.Out.printLn("Processed Item" +item.id) // consider item as the name of reference variable for current iteration

一切一段時間沒事了,我可以看到兩條線程同時工作。但過了一段時間,其中一個線程已停止處理。只有一個線程正在運行。 (我知道這一點,因爲我可以在控制檯上看到ID給線程2的內容不再被打印)。

有誰知道這是怎麼發生的?我的意思是爲什麼ExecutorService停止運行第二個線程。

感謝您的幫助提前。

添加示例代碼我以前做過:

public List<Output> processInputs(List<Input> inputs) 
     throws InterruptedException, ExecutionException { 

    int threads = Runtime.getRuntime().availableProcessors(); 
    ExecutorService service = Executors.newFixedThreadPool(threads); 

    List<Future<Output>> futures = new ArrayList<Future<Output>>(); 
    for (final Input input : inputs) { 
     Callable<Output> callable = new Callable<Output>() { 
      public Output call() throws Exception { 
       Output output = new Output(); 
       // process your input here and compute the output 
       return output; 
      } 
     }; 
     futures.add(service.submit(callable)); 
    } 

    service.shutdown(); 

    List<Output> outputs = new ArrayList<Output>(); 
    for (Future<Output> future : futures) { 
     outputs.add(future.get()); 
    } 
    return outputs; 
+0

請編輯您的問題以包含您程序中的相關代碼。理想情況下,你應該包含一個能夠重現問題的[mcve]。 – Kenster

+0

這可能不會實際停止。它可能處於等待狀態。檢查非工作線程的運行方法並查看最後執行哪一行。 – pikrut

+0

@pikrut我已經使用'Callable',所以沒有run()方法。其次Callable是在for循環中創建的(1個子列表可調用)。這意味着這兩個子列表的調用方法實現是相同的。 – Aman

回答

1

一切都很好了一段時間,我可以看到兩個線程同時工作。但過了一段時間,其中一個線程已停止處理。只有一個線程正在運行。 (我知道這一點,因爲我可以在控制檯上看到ID給線程2的內容不再被打印)。

我懷疑你的處理線程拋出了異常。 Future.get()方法可以拋出ExecutionException"if the computation threw an exception"

// the following might throw an exception if the background job threw 
outputs.add(future.get()); 

如果有一個NPE,一個IOException,等你「處理您輸入」代碼,然後該異常被拋出Callable拋出並存儲在Future因此它可以通過get()方法拋出,但包裹在ExecutionException。這很有用,所以正在等待的線程可以獲取和處理(記錄等)由後臺線程拋出的異常。

而不是隻讓你的processInputs(...)方法拋出異常的地方它可能會迷路來電,我會做這樣的事情在你的while循環以下事項:

try { 
    outputs.add(future.get()); 
} catch (InterruptedException ie) { 
    // always a good pattern if the thread that is waiting was interrupted 
    Thread.currentThread().interrupt(); 
    return; 
} catch (ExecutionException ee) { 
    // somehow log the error 
    logger.error("Computation failed to process", ee); 
    // now continue and get the next future in the list 
} 

如果你沒有趕上並妥善處理ExecutionException,那麼處理異常也會終止調用processInputs(...)的線程。

+0

你是絕對正確的,我得到了get()方法的ExecutionException。我已經捕捉到了這兩個異常,並且正在我的控制檯上打印堆棧跟蹤。重新處理線程1的數據並獲得輸出是否有意義?或者我應該重新運行程序並查看是否再次拋出異常?我的意思是我可以做更好的事情,比我在代碼中記錄這些錯誤的情況更好嗎? – Aman

+0

不確定@Aman。這取決於你在做什麼。如果你的處理方法可能再次運行,那麼確定你可以再試一次。我認爲您需要了解_why_例外情況以及是否重試有意義。 – Gray

+0

好的,我會檢查。感謝您的解釋,我接受您的答案。我得到這個例外 :java.util.concurrent.ExecutionException: org.apache.openjpa.util.StoreException:用盡結果集\t \t在java中。 util.concurrent.FutureTask $ Sync.innerGet(FutureTask.java:233) \t at java.util.concurrent.FutureTask.get(FutureTask.java:94) – Aman