从Java中的多线程程序终止特定线程

时间:2009-10-14 12:55:53

标签: java multithreading

正在使用Java编写程序,如下所示,该类只是在操作系统级别执行命令。然而,有时我们遇到程序卡住的问题,因此命令永远不会返回任何状态,因此线程不会终止。

现在我正在尝试增强代码,添加一个额外的东西,我可以杀死特定的线程。我已经捕获了ThreadId,所以,这可行吗?

public class ExecuteCmd implements Runnable {

String ProcessId;
String cmd;
BackendSQL bsql;
Logger myLogger;
Thread myThread;


public ExecuteCmd(String cmd, BackendSQL bsql, String ProcessId, Logger myLogger) { 
   this.ProcessId=ProcessId; 
   this.cmd=cmd; 
   this.bsql=bsql;
   this.myLogger=myLogger;
}

public void run() {
    int rc = 0;

    try {

        long ThreadId = Thread.currentThread().getId();


        bsql.MarkRunning(ProcessId, ThreadId);

        myLogger.debug("[ExecuteCmd] Command is: "+cmd);

        String[] cmdFull = cmd.split(";");

        Runtime rt = Runtime.getRuntime();

        Process p = rt.exec(cmdFull);
        myLogger.info("[ExecuteCmd] [Threading] "+ ThreadId + ": Executing command");
        myLogger.debug("[ExecuteCmd] Command is: "+cmd);


        BufferedReader inStream = new BufferedReader(new InputStreamReader(p.getInputStream()));

        String inStreamLine = null;
        String inStreamLinebyLine=null;
        while((inStreamLine = inStream.readLine()) != null) {
          inStreamLinebyLine = inStreamLinebyLine+"\n"+inStreamLine;
        }
        myLogger.info("Command getInputStream: " + inStreamLinebyLine);



        try {
            rc = p.waitFor();

            if (rc == 0) {
                bsql.MarkCompleted(ProcessId);
            }else{
                bsql.MarkFailed(ProcessId);
            }

        } catch (InterruptedException intexc) {
            System.out.println("Interrupted Exception on waitFor: " +
                               intexc.getMessage());
        }

    }catch (IOException IOE) {
        myLogger.error("IOException[ExecuteCmd]: " + IOE.getMessage());
    }catch (Exception e) {
        myLogger.error("Exception[ExecuteCmd]: " + e.getMessage());
    }
}

}

3 个答案:

答案 0 :(得分:3)

您应该将ExecuteCmd的实例提交给ExecutorService。这样,您就可以取消或中断任务。

Process#waitFor()是一个可中断的操作,因此它应该可以正常工作。

ExecutorService service = Executors.newSingleThreadedExecutor();
Future<?> future = service.submit(new ExecuteCmd(...));
if (takingTooLong()) {
    future.cancel(true);
}

答案 1 :(得分:1)

要解决您的基本问题(以及为什么需要中断某个过程),我怀疑您的流程已暂停,因为您没有消耗标准输出和标准错误并发。基本上,如果您不这样做,那么您生成的进程可能会挂起。这是一个非常普遍的问题。有关详细信息和修复,请参阅this answer

另请参阅this Java Specialist newsletter有关如何干净地关闭线程(通过Thread.interrupt()),以及如何在正在关闭的线程中正确处理此问题。即使您使用Executor框架等,也需要正确处理关闭,因为它们会中断您的线程。

但是,如果你同时使用你的程序stdout / err,我不相信你会需要这个。

答案 2 :(得分:0)

我认为Thread.Interrupt是你要找的东西,你必须从另一个线程调用它。

http://java.sun.com/javase/6/docs/api/java/lang/Thread.html#interrupt%28%29