java线程等待死进程完成

java线程等待死进程完成,java,multithreading,process,Java,Multithreading,Process,我编写了一个java类来执行多线程任务,每个任务运行一个外部进程。 该过程负责将“.chp”文件转换为“.txt”文件。它是用C写的 此过程在某一点中断,因为它在查看终端中的“顶部”时消失(可能是由于chp文件损坏)。问题是java线程中的进程没有返回。“process.waitFor()”似乎一直在运行(至少在我为ExecutorService指定的12个小时之前) 我是否做错了什么(没有发现异常?)? 我尝试在MyThread中设置一个String类型的类变量,并将一条错误消息放在抛出新的R

我编写了一个java类来执行多线程任务,每个任务运行一个外部进程。 该过程负责将“.chp”文件转换为“.txt”文件。它是用C写的

此过程在某一点中断,因为它在查看终端中的“顶部”时消失(可能是由于chp文件损坏)。问题是java线程中的进程没有返回。“process.waitFor()”似乎一直在运行(至少在我为ExecutorService指定的12个小时之前)

我是否做错了什么(没有发现异常?)? 我尝试在MyThread中设置一个String类型的类变量,并将一条错误消息放在抛出新的RuntimeException的位置,然后在main的末尾打印字符串,但线程代码没有达到这一点。它仍然停留在waitFor()

当C程序失败时,进程不应该终止吗

程序在终端上打印(cf:MyThread):

主要内容:


您可以让主线程等待一段合理的时间,然后调用
MyThread
类上的某个方法来终止已启动的进程,从而导致线程完成。

如果我理解正确,您的Java线程在C程序崩溃后仍在等待


使生成的C进程发送心跳。您甚至可以通过将某个内容打印到控制台(或插入表格)来完成此操作让Java线程经常醒来并检查心跳。如果没有心跳,则假设C进程停止并终止线程。

正如我经常建议的那样,在使用消息处理解决方案使您的C程序与Java应用程序交互时,使用更健壮和专业的观点,这将变得简单和干净为了避免那些非守护进程线程因为C应用程序崩溃而永远等待…现在所有代理都有一个STOMP接口,它对于任何类型的应用程序调用都非常酷(只需使用任何Http库),代理配置将允许重新启动未完成的作业,设置一些超时,等等。即使JMS不支持请求和响应,也很容易实现这种范例


Jerome

在Java中启动外部进程可能会有点棘手。我通常会尽量避免它们,因为您将不得不处理不同的错误代码和一些终端错误。我建议您使用专门的库,如commons exec(http://commons.apache.org/exec/)

您的C程序是否可能正在标准输出上生成输出?如果是,您需要在Process.waitFor()返回之前读取Process.getOutputStream()-请参阅

或者,调用一个重定向stdout的shell脚本的C程序


您可以使用jstack命令确认该线程确实在Process.waitFor()上被阻塞。

问题是我不知道每个线程运行需要多少时间。只要一个线程在ExecutorService中占据一席之地(最多4个线程),另一个无法启动,这很烦人……此外,我想知道为什么当外部程序中断时进程不返回!@Eric:你应该有某种故障保护机制,以防进程永远不会终止,比如超时后你会终止进程。ExecutorService会有一个超时ch保证程序最终会结束。不过线程可以在5分钟内返回,也可以持续数小时。如果进程在2分钟后中断,即使我在5小时后设置了超时,我的执行器中也会出现5小时的死进程…这不是很令人满意!!但你不能像10秒钟那样等待吗启动所有线程后,在主线程中执行
Thread.sleep
,然后在每个线程上调用一个方法,如果进程尚未完成,该方法将终止进程?我如何知道进程是否应终止?如果进程停留在waitFor()中模式,我猜它仍然是活动的,不管C程序是否已损坏…这是我不理解的一点。如果基础程序损坏,该进程如何生存?我不确定我理解你所说的“打印某物”是什么意思!如果你的意思是修改C程序,那是不可能的。我没有必要的技能,这是一个相当大的程序。是的,我的意思是修改它以打印一些东西或将一些东西发送到数据库,以便Java方面可以检查它。据我理解你的答案,你说的是一个web应用程序。但我的Java程序是一个独立程序ne cmd行应用程序。尚未测试,很难重现该情况,但如果“bug”(如果它确实是一个)仍然是我们今天可以体验到的东西(您的链接很旧;)。它很有效!!您确实必须使用程序的输出,才能让waitFor()返回!!
A
B
C
String pathToBin = "/path/to/bin";
List<MyThread> threadList = new ArrayList<MyThread>();

for (File f : folderList) {
    File[] chpFilesInFolder = f.listFiles(new FilenameFilter() {

        @Override
        public boolean accept(File dir, String name) {
            if (name.endsWith(".chp")){
                 return true;
            }else{
                 return false;
            }
        }
    });
    File chpFile = writeChpFiles(chpFilesInFolder);
    String[] cmd = {pathToBin, "--arg1", chpFile, "--out-dir", outputFolder};
    MyThread t = new MyThread(cmd, f, chpFilesInFolder);
    threadList.add(t);
}

ExecutorService threadExecutor = Executors.newFixedThreadPool(4);
for(MyThread th : threadList){
    threadExecutor.execute(th);
}
threadExecutor.shutdown();

try {
    threadExecutor.awaitTermination(12, TimeUnit.HOURS);
} catch (InterruptedException e) {
    e.printStackTrace();
}
class MyThread extends Thread{
    private String[] cmd;
    private File chpFolder;
    private File[] chpFilesInFolder;

    public MyThread(String[] cmd, File chpFolder, File[] chpFilesInFolder){
        this.cmd = cmd;
        this.chpFolder = chpFolder;
        this.chpFilesInFolder = chpFilesInFolder;
    }

    @Override
    public void run() {
        Process process = null;
        try{
            System.err.println("A ");
            ProcessBuilder procBuilder = new ProcessBuilder(cmd);
            procBuilder.redirectErrorStream(true);

            System.err.println("B");
            process = procBuilder.start();

            System.err.println("C");
            process.waitFor();

            System.err.println("D");
            if(process.exitValue()!=0) System.err.println("ERROR !"+process.exitValue());

            System.err.println("E");
        }catch(IOException e){
            e.printStackTrace();
        }catch(InterruptedException e){
            e.printStackTrace();
        }catch(Throwable e){
            e.printStackTrace();
        }finally{
            System.err.println("F");
            if(process!=null) {try { process.destroy();} catch(Exception err) {err.printStackTrace();}}
        }

        File[] txtFilesInFolder = chpFolder.listFiles(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
                if (name.endsWith(".chp.txt")){
                    return true;
                }else{
                    return false;
                }
            }
        });

        if (txtFilesInFolder.length==chpFilesInFolder.length){
            for (File chp : chpFilesInFolder) {
                chp.delete();
            }
            File logFile = new File(chpFolder, "apt-chp-to-txt.log");
               if (logFile.exists()){
                   logFile.delete();
               }
        }else{
            throw new RuntimeException("CHPs have not all been transformed to TXT in "+chpFolder.getAbsolutePath());
        }