2012-10-16 136 views
2

於是我問了一個問題前陣子:Over here說問這個問題:「我怎樣才能使他們是否花費太長時間我的線程會被殺掉」爲什麼我的線程在失敗時超時?

我已經實現了那裏,但在某些罕見的情況下提到的解決方案,其中線程超時,程序仍可能失敗/鎖定(請參閱:保持main()方法處於打開狀態,並阻止程序的進一步cron運行)。

下面是我使用的源:

//Iterate through the array to submit them into individual running threads. 
    ExecutorService threadPool = Executors.newFixedThreadPool(12); 
    List<Future<?>> taskList = new ArrayList<Future<?>>(); 
    for (int i = 0; i < objectArray.length; i++) { 
     Future<?> task = threadPool.submit(new ThreadHandler(objectArray[i], i)); 
     taskList.add(task); 
     Thread.sleep(500); 
    } 

    //Event handler to kill any threads that are running for more than 30 seconds (most threads should only need .25 - 1 second to complete. 
    for(Future future : taskList){ 
     try{ 
      future.get(30, TimeUnit.SECONDS); 
     }catch(CancellationException cx){ System.err.println("Cancellation Exception: "); cx.printStackTrace(); 
     }catch(ExecutionException ex){ System.err.println("Execution Exception: ");ex.printStackTrace(); 
     }catch(InterruptedException ix){ System.err.println("Interrupted Exception: ");ix.printStackTrace(); 
     }catch(TimeoutException ex) {future.cancel(true);} 
    } 
    threadPool.shutdown(); 
    threadPool.awaitTermination(60, TimeUnit.SECONDS); 

所以我的問題是:這個代碼實現,爲什麼是執行服務爲30秒不切東西了。

+1

注意:每個任務的超時時間都會增加。例如如果第一項任務需要29秒,則第二項任務需要59秒才能完成。 –

+0

你可以評論如何解決這個問題嗎?因爲這不是意圖。 –

+0

我添加了一個答案/解決超時時間較長的原因之一。 –

回答

4

因爲我懷疑你的工作線程仍在運行。你打電話給future.cancel(true);,但是所有的功能是在線程上設置中斷標誌 - 它不會主動中斷你的運行代碼。另一種「中斷」代碼的方法是設置一些volatile boolean shutdown標誌爲真,並在代碼中測試該標誌。看到這裏爲more details about interrupting threads

您需要確保您的ThreadHandler代碼正確處理中斷。例如,它需要在循環或其他代碼塊中檢查Thread.currentThread().isInterrupted()。您還需要確保正確處理InterruptedException,而不僅僅是吞嚥中斷。

有關線程中斷的更多信息,請參閱my answer here

+0

Hrm,這將是真正難以處理我目前的數據結構。所有這些傳遞給它的方法都非常簡單:基本上它做了一個object.run(),因此每個對象都有自己的線程。沒有循環運行,如果我做循環,我最終會使用每個對象很多次,這會導致很多問題。 –

+0

在'object.run()'方法中,你必須能夠檢測線程是否被中斷。這意味着你將不得不在你的代碼中測試Thread.currentThread()。isInterrupted()'。這些物體在做什麼? – Gray

+0

好吧,每個線程都有自己的一套工作,但是他們正在從在線資源中提取特定的數據來預測事件......我不能說沒有違反NDA的就更多。 –

1

您對每個任務的超時數量可能並不是預期的。相反,您可以在超時後關閉線程池並取消其他線程池。

threadPool.shutdown(); 
threadPool.awaitTermination(30, TimeUnit.SECONDS); 
threadPool.shutdownNow(); // interrupt any running tasks. 
0

Java書面併發實踐中有一整章專用任務取消。從我讀過的任務取消必須在finally塊中確保任務總是結束。

try{ 
      future.get(30, TimeUnit.SECONDS); 

     } catch (TimeoutException e) { 
      // log error message and falls through to finally block 
     } catch (ExecutionException e) { 
      throw e; 
     } finally { 
      future.cancel(true); // interrupt task 
     } 

處理InterruptedException時必須恢復中斷狀態。

  catch (InterruptedException e) { 
       Thread.currentThread().interrupt(); 
      } 

在ThreadHandler任務檢查Thread.currentThread()。isInterrupted()標誌,並拋出一個InterruptedException如果屬實傳播中斷狀態。

相關問題