2012-01-11 22 views
1

私はいくつかのパラメータで別のアプリケーションを起動するJavaアプリケーションを持っています。その間にJavaを続行し、ユーザー入力後に他のアプリケーションを強制終了することができます。 Thread.Stop()が推奨されていないため、これを読んで、Thread.Interupt()を使用してください。 スレッドでは、InterruptedExectionがスローされます。だから私が持っているものがある:procThread.interrupt()が実行されますどのようにこれまでスレッドによって制御されるプロセスを停止するにはどうすればよいですか?

private List<Thread> activeProccesses = new ArrayList<Thread>(); 

public void StartProcess(int id, String message) { 
    System.out.println("StartProcess: id=" + id + ", message='" + message + "'"); 

    StopAllProcesses(); 

    ProcessExecutor proc = new ProcessExecutor(id, message); 
    Thread procThread = new Thread(proc); 
    activeProccesses.add(procThread); 
    procThread.start(); 
} 

public void StopAllProcesses() { 
    System.out.println("Stopping all processes"); 

    Iterator<Thread> it = activeProccesses.iterator(); 

    while (it.hasNext()) { 
     Thread procThread = it.next(); 

     if (procThread.isAlive()) { 
      procThread.interrupt();    
     } 

     it.remove(); 
    } 

    System.out.println("Stopping all processes: done");   
} 

しかしcatch(InterruptedException ex)は決してヒットしない:

public class ProcessExecutor extends Object implements Runnable { 
    private volatile int id; 
    private String message; 
    private Process proc = null; 

    public ProcessExecutor(int id, String message) { 

     this.id = id; 
     this.message = message; 
    } 

    public int GetId() { 
     return id; 
    } 

    public void run() { 
     try { 
      String[] cmd = new String[4]; 
      cmd[0] = "path to some app"; 
      cmd[1] = id; 
      cmd[2] = message; 

      Runtime rt = Runtime.getRuntime(); 
      proc = rt.exec(cmd); 

      BufferedReader input = new BufferedReader(new InputStreamReader(proc.getInputStream())); 

      String line=null; 

      while ((line=input.readLine()) != null) { 
       System.out.println("ProcessExecutor: " + line); 
      } 

      int exitVal = proc.waitFor(); 

      System.out.println("ProcessExecutor: Exited with error code " + exitVal); 
     } catch(InterruptedException ex) { 
      System.out.println("ProcessExecutor: stopping"); 

      if (proc != null) {    
       proc.destroy(); 
       proc = null; 
      }   
     } catch(Exception e) { 
      System.out.println("ProcessExecutor: exception: " + e.toString()); 
      e.printStackTrace(); 
     } 
    } 
} 

によって処理されています。

どうしてこの問題を修正できますか?

編集:結論

は、スレッドが、私が直接、その後input.readLine()をブロック解除Processを停止しなければならなかったことを停止するようにinput.readLine() INORDERによってブロックされたが判明します。

public class ProcessExecutor extends Thread { 
    private volatile int id; 
    private String message; 
    private volatile Process proc = null; 

    public ProcessExecutor(int id, String message) { 
     this.id = id; 
     this.message = message; 
    } 

    public int GetId() { 
     return id; 
    } 

    public void StopProc() { 
     if (proc != null) { 
      proc.destroy(); 
     } 
    } 

    public void run() { 
     try { 
      String[] cmd = new String[4]; 
      cmd[0] = "path to some app"; 
      cmd[1] = id; 
      cmd[2] = message; 

      Runtime rt = Runtime.getRuntime(); 
      proc = rt.exec(cmd); 

      BufferedReader input = new BufferedReader(new InputStreamReader(proc.getInputStream())); 

      String line=null; 

      while ((line=input.readLine()) != null) { 
       System.out.println("ProcessExecutor: " + line); 
      } 

      int exitVal = proc.waitFor(); 
      proc = null; 

      System.out.println("ProcessExecutor: Exited with error code " + exitVal);   
     } catch(Exception e) { 
      System.out.println("ProcessExecutor: exception: " + e.toString()); 
      StopProc(); 
     } 
    } 
} 

private List<ProcessExecutor> activeProccesses = new ArrayList<ProcessExecutor>(); 

public void StartProcess(int id, String message) { 
    System.out.println("StartProcess: id=" + id + ", message='" + message + "'"); 

    StopAllProcesses(); 

    ProcessExecutor proc = new ProcessExecutor(id, message); 
    activeProccesses.add(proc); 
    proc.start(); 
} 

public void StopAllProcesses() { 
    System.out.println("Stopping all processes"); 

    Iterator<ProcessExecutor> it = activeProccesses.iterator(); 

    while (it.hasNext()) { 
     ProcessExecutor proc = it.next(); 

     proc.StopProc(); 
     it.remove(); 
    } 

    System.out.println("Stopping all processes: done");   
} 
+0

スレッドとプロセスは2つの異なるものです。プロセスを強制終了するには、 'destroy'メソッドを呼び出します。プロセスの終了を待っているスレッドを中断してもプロセスは終了しません。 –

+0

InterruptedExceptionがスローされている場合は、proc.destroy();でプロセスを強制終了できます。しかし、InterruptedExceptionがスローされないのはなぜですか? – RvdK

+0

おそらく、スレッドがプロセス入力ストリームから行を読み込むのがブロックされているため、このブロッキング呼び出しは中断できません。 –

答えて

0

私がコメントしたように。私はスレッドを中断する唯一の方法は、スレッドの読み込みをブロックするプロセスをkillすることだと思います。スレッドを中断する唯一の解決策はソケットを閉じることです。

プロセスを破棄するメソッドをスレッドに追加します。

+0

正しく、これは私がやったことであり、それは動作します:)将来の参照のために解決策を使って質問を更新してください。 – RvdK

+0

送信者プロセスをブロックして受信者を停止しますか?それはひどい解決策です。少なくとも、受信者がきれいに出るように、「ストリームの終わり」を送ることができます。最善の解決策は、最初は無期限にブロックしないことです。 – Viruzzo

+0

読み取りメソッドはすべてブロックメソッドです。無期限にブロックする以外の方法はありません。プロセスをより優雅に停止することができれば、当然のことです。しかしそれはプロセス固有のものです。 –

0

ProcessExecutorで中断された状態を明示的にチェックする必要があります。 InterruptedExceptionは自動的にスローされません。このようなもの:

public class ProcessExecutor extends Object implements Runnable { 

    public void run() { 
    try { 
     //other code.... 

     while ((line=input.readLine()) != null) { 
      System.out.println("ProcessExecutor: " + line); 
      if (Thread.interrupted()) { 
       // We've been interrupted! 
       throw new InterruptedException("...."); 
      } 
     } 
    } catch(InterruptedException ex) { 
     System.out.println("ProcessExecutor: stopping"); 
} 

詳細はhttp://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.htmlを参照してください。

+0

ちょうどそれを試して、同じ問題があります。スレッドがreadLineでブロックされています。 – RvdK

0

割り込みスレッドは特定の状態にある場合にのみ機能し、通常はデータをアクティブに処理していないときに実行されるwait()呼び出し中に実行されます。

readLine()のコールでスレッドを終了させたい場合は、try-catchを使用する代わりにinterrupted()をwhileチェックでチェックすることができます。

編集:ready()が実際に単一の文字をチェックしているので

while (true) 
{ 
    if (input.ready()) 
    { 
     line = input.readLine(); 
     System.out.println("ProcessExecutor: " + line); 
    } else { 
     try { Thread.sleep(100); } // time to wait in ms 
     catch (InterruptedException ie) { break; } 
    } 
} 

があなたの代わりにreadLine()の連続read()を使用する必要があるでしょう、あなたの問題を解決する最良の方法がありますが、ストリームライン上に書いた場合一度にこのような違いはありません。待つ時間は明らかに任意です。

0

私はスレッドを停止するより優雅な方法を提案します。 runメソッドでは、あなたがProcessExecutorでコード

while ((line=input.readLine()) != null) { 
       System.out.println("ProcessExecutor: " + line); 
      } 

を以下している、そのゲッターとセッターを伴うブールフィールドを追加します。

private Boolean stop = false; 

と同じ条件でフラグを確認してください。 StopAllProcesses()方法で

while (((line=input.readLine()) != null) && !stop) { 
        System.out.println("ProcessExecutor: " + line); 
       } 

ProcessExecutorインスタンスでstop=trueを設定します。これにより、run()メソッドが返され、正常にスレッドを停止します。

+0

これは、Jeremiah Orrのソリューションと同等の目的と目的のためであり、同じ欠陥を共有しています。読み込みをブロックされてもスレッドは終了しません。 – Viruzzo

+0

はい! OPは明示的に_blocking_条件を記述する必要があります。それはOPが私が推測したいものです。 – Santosh

+0

私はreadLineがブロックしていることを知らなかった。私はスレッドが停止していないことを見ただけです。 – RvdK

関連する問題