【问题标题】:Terminating a specific thread from a Multi-Threading program in Java从 Java 中的多线程程序中终止特定线程
【发布时间】:2009-10-14 12:55:53
【问题描述】:

我正在编写如下所示的 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());
    }
}

}

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      但是,如果您同时使用程序 stdout/err,我认为您不需要这个。

      【讨论】:

      • Brian 不仅该页面过于复杂而且有些不正确(他应该检查 Thread.isInterrupted(),而不是休眠,而且他不应该扩展 Thread),它已经过时了 7 年。 java.util.concurrent 消除了直接与 Thread 类交互的需要。
      • 它可能已经 7 岁了,但它仍然完全有效。至于使用 java.util.concurrent 包是否更好,这是另一个问题。如何停止线程以及如何正确处理它的基本问题仍然存在。
      • 事实上你会看到他正在使用 Thread.isInterrupted() (最后一个例子,如果没记错的话)
      【解决方案3】:

      我认为 Thread.Interrupt 是您正在寻找的,但您必须从另一个线程调用它。

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

      【讨论】:

        猜你喜欢
        • 2023-03-28
        • 1970-01-01
        • 1970-01-01
        • 2014-11-18
        • 2023-02-20
        • 2015-12-21
        • 1970-01-01
        • 2014-01-24
        • 2019-06-25
        相关资源
        最近更新 更多