2017-03-15 37 views
0

我需要設置一段代碼的超時時間,它將調用jar文件中的方法。 我使用下面的代碼如何檢測未知的線程池並將其關閉?

final Runnable stuffToDo = new Runnable() { 
      @Override 
      public void run() { 
      /* Do stuff here. */ 
       jarclass.run(); 
      } 
    }; 

    final ExecutorService executor = Executors.newFixedThreadPool(1); 
    final Future future = executor.submit(stuffToDo); 
    //executor.shutdown(); // This does not cancel the already-scheduled task. 
    try { 
     future.get(1, TimeUnit.SECONDS); 
    } 
    catch (InterruptedException ie) { 
     /* Handle the interruption. Or ignore it. */ 
    } 
    catch (ExecutionException ee) { 
     /* Handle the error. Or ignore it. */ 
    } 
    catch (TimeoutException te) { 
     /* Handle the timeout. Or ignore it. */ 
    } 
    if (!executor.isTerminated()){ 
     executor.shutdownNow(); 
    } 

然而jarclass.run()莫名其妙地開始其繼續運行另一個線程,並顯示所有帶游泳池-2線程1的打印輸出。

如何完全關閉jarclass.run()?

更新: 我將新線程()更改爲新的Runnable。它仍然不起作用。 我很困惑的是我不知道jarclass在哪裏啓動另一個線程並且無法處理它。當代碼進入executor.shutdownNow()時,它會跳出並運行以下代碼。但jarclass.run()仍在運行。 我不擅長英語。希望我明確這一點。

更新:

問題這段代碼解決:

Future<String> future = new FutureTask<String>(new Callable<String>() { 
     public String call() throws Exception { 
      jarclass.run(); 
      return null; 
     } 
    }); 

    try { 
     future.get(1, TimeUnit.SECONDS); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

不知道爲什麼以前的代碼失敗......如果有誰知道,我們仍然可以商量。

非常感謝您的回覆。真的很感激它。

+0

您可能要直接使用一個線程,並調用其*中斷*方法。但我不確定這是否會奏效。 – GhostCat

+0

['shutdown'](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown--)只會阻止添加新任務,但允許已經運行的任務完成:「啓動一個有序關閉,其中執行先前提交的任務,但不會接受任何新任務。」您可以嘗試調用['cancel'](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html#cancel-boolean-)(中斷)未來在TimeoutException。 – Fildor

+0

順便說一句:你不需要做stuffToDo一個'新的線程','新的Runnable'會做。這看起來很奇怪,因爲它是一個接口,但實際上你正在創建一個實現接口的匿名類。 – Fildor

回答

0

使用ExecutorService時,您不應該實例化Thread。使用Runnable代替:

final Runnable stuffToDo = new Runnable() { /* as it is now */ }; 

當你創建一個線程,直接,它不是由你以後創建執行服務管理的,這就是爲什麼所有的日誌。

+0

我不這麼認爲。我同意他應該使用'new Runnable',但將它傳遞給ExecutorService意味着Service將使用Thread的'run'方法。由於他不啓動線程,它仍然可以工作。 – Fildor

0

這不是安全殺死線程直接看到Thread.stop() deprecated

Recomended方式,它使用一個標誌,可以通知到線程是時候停止。

如果可以訪問JAR和修改代碼,你可以創建一個標誌使用,所以當你需要殺死過程中,你可以調用jarclass.stop()命名爲您jarclassstop()方法。

例如:

public class jarclass{ 

    private boolean keepAlive = true; 

    public void run(){ 

    keepAlive = true; 
    while(keepAlive){ 
     //do work 
    } 
    } 

    public void stop(){ 
    keepAlive = false; 
    } 
} 
+0

這可能會起作用,但由於某些版權問題,我會考慮更改jarclass作爲最後一個選項。希望我能想出其他解決方案。不過謝謝。 – user1703532

+0

是不是一個很好的解決方案,但如果方法run()jarclass啓動一個新的線程,你沒有任何引用,我看到一些解決方案 –

+0

我不確定run()是否已經開始一個新的線程或不。我通過jarclass代碼,但沒有找到任何新的Thread()語句。但run()中的所有消息都是使用pool-2-thread-1打印的。主程序流程跳過了jarclass.run(),但沒有終止它。 – user1703532